diff --git a/src/liquid/components/ld-toggle/ld-toggle.tsx b/src/liquid/components/ld-toggle/ld-toggle.tsx
index 4d5e85c147..4ba8912c0f 100644
--- a/src/liquid/components/ld-toggle/ld-toggle.tsx
+++ b/src/liquid/components/ld-toggle/ld-toggle.tsx
@@ -1,4 +1,4 @@
-import { Component, Element, h, Host, Method, Prop } from '@stencil/core'
+import { Component, Element, h, Host, Method, Prop, Watch } from '@stencil/core'
import { getClassNames } from '../../utils/getClassNames'
/**
@@ -18,6 +18,7 @@ import { getClassNames } from '../../utils/getClassNames'
export class LdToggle implements InnerFocusable {
@Element() element: HTMLElement
private input: HTMLInputElement
+ private hiddenInput: HTMLInputElement
private hasIcons: boolean
/** Size of the toggle. */
@@ -26,6 +27,12 @@ export class LdToggle implements InnerFocusable {
/** Disabled state of the toggle. */
@Prop() disabled: boolean
+ /** Used to specify the name of the control. */
+ @Prop() name: string
+
+ /** The input value. */
+ @Prop() value: string
+
/** Alternative disabled state that keeps element focusable */
@Prop() ariaDisabled: string
@@ -33,7 +40,7 @@ export class LdToggle implements InnerFocusable {
@Prop({ mutable: true, reflect: true }) checked: boolean
/** Set this property to `true` in order to mark the toggle as required. */
- @Prop() required: false
+ @Prop() required: boolean
/**
* Sets focus on the toggle
@@ -45,10 +52,42 @@ export class LdToggle implements InnerFocusable {
}
}
+ @Watch('checked')
+ @Watch('name')
+ @Watch('required')
+ @Watch('value')
+ updateHiddenInput() {
+ if (this.hiddenInput) {
+ this.hiddenInput.checked = this.checked
+ this.hiddenInput.name = this.checked && this.name ? this.name : ''
+ this.hiddenInput.required = this.required
+ this.hiddenInput.value = this.value ?? (this.checked ? 'on' : '')
+ }
+ }
+
componentWillLoad() {
this.hasIcons =
!!this.element.querySelector('[slot="icon-start"]') ||
!!this.element.querySelector('[slot="icon-end"]')
+
+ if (this.element.closest('form')) {
+ this.hiddenInput = document.createElement('input')
+ this.hiddenInput.required = this.required
+ this.hiddenInput.type = 'hidden'
+
+ if (this.value || this.checked) {
+ this.hiddenInput.value = this.value ?? 'on'
+ }
+ if (this.checked) {
+ this.hiddenInput.checked = true
+
+ if (this.name) {
+ this.hiddenInput.name = this.name
+ }
+ }
+
+ this.element.appendChild(this.hiddenInput)
+ }
}
private handleBlur = (ev: FocusEvent) => {
diff --git a/src/liquid/components/ld-toggle/readme.md b/src/liquid/components/ld-toggle/readme.md
index 9d31428d93..126ae80adf 100644
--- a/src/liquid/components/ld-toggle/readme.md
+++ b/src/liquid/components/ld-toggle/readme.md
@@ -379,6 +379,7 @@ Please refer to the [ld-label](components/ld-label/) docs for more information o
{% example %}
+
@@ -443,6 +444,7 @@ Please refer to the [ld-label](components/ld-label/) docs for more information o
| `checked` | `checked` | The input value. | `boolean` | `undefined` |
| `disabled` | `disabled` | Disabled state of the toggle. | `boolean` | `undefined` |
| `key` | `key` | for tracking the node's identity when working with lists | `string \| number` | `undefined` |
+| `name` | `name` | Used to specify the name of the control. | `string` | `undefined` |
| `ref` | `ref` | reference to component | `any` | `undefined` |
| `required` | `required` | Set this property to `true` in order to mark the toggle as required. | `boolean` | `undefined` |
| `size` | `size` | Size of the toggle. | `"lg" \| "sm"` | `undefined` |
diff --git a/src/liquid/components/ld-toggle/test/__snapshots__/ld-toggle.spec.ts.snap b/src/liquid/components/ld-toggle/test/__snapshots__/ld-toggle.spec.ts.snap
index ec09b7826e..aed4872d36 100644
--- a/src/liquid/components/ld-toggle/test/__snapshots__/ld-toggle.spec.ts.snap
+++ b/src/liquid/components/ld-toggle/test/__snapshots__/ld-toggle.spec.ts.snap
@@ -1,5 +1,15 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`ld-toggle creates hidden input field, if inside a form 1`] = `
+
+
+
+
+
+
+
+`;
+
exports[`ld-toggle prevents input value changes with an aria-disabled attribute 1`] = `
diff --git a/src/liquid/components/ld-toggle/test/ld-toggle.spec.ts b/src/liquid/components/ld-toggle/test/ld-toggle.spec.ts
index 50e4fbdc46..1d015f84db 100644
--- a/src/liquid/components/ld-toggle/test/ld-toggle.spec.ts
+++ b/src/liquid/components/ld-toggle/test/ld-toggle.spec.ts
@@ -118,4 +118,75 @@ describe('ld-toggle', () => {
expect(input.focus).toHaveBeenCalled()
})
+
+ it('creates hidden input field, if inside a form', async () => {
+ const { root } = await newSpecPage({
+ components: [LdToggle],
+ html: ``,
+ })
+ expect(root).toMatchSnapshot()
+ })
+
+ it('sets initial state on hidden input', async () => {
+ const { root } = await newSpecPage({
+ components: [LdToggle],
+ html: ``,
+ })
+ expect(root.querySelector('input')).toHaveProperty('checked', true)
+ expect(root.querySelector('input')).toHaveProperty('name', 'example')
+ expect(root.querySelector('input')).toHaveProperty('required', true)
+ expect(root.querySelector('input')).toHaveProperty('value', 'on')
+ })
+
+ it('updates hidden input field', async () => {
+ const { root, waitForChanges } = await newSpecPage({
+ components: [LdToggle],
+ html: ``,
+ })
+
+ root.setAttribute('name', 'test')
+ await waitForChanges()
+
+ expect(root.querySelector('input')).toHaveProperty('value', '')
+ expect(root.querySelector('input')).toHaveProperty('checked', false)
+ expect(root.querySelector('input')).toHaveProperty('required', false)
+ expect(root.querySelector('input')).toHaveProperty('name', '')
+
+ root.dispatchEvent(new Event('click'))
+ root.setAttribute('required', '')
+ await waitForChanges()
+
+ expect(root.querySelector('input')).toHaveProperty('checked', true)
+ expect(root.querySelector('input')).toHaveProperty('required', true)
+ expect(root.querySelector('input')).toHaveProperty('value', 'on')
+
+ root.setAttribute('name', '')
+ root.setAttribute('value', 'test')
+ await waitForChanges()
+
+ expect(root.querySelector('input')).toHaveProperty('value', 'test')
+ expect(root.querySelector('input')).toHaveProperty('checked', true)
+ expect(root.querySelector('input')).toHaveProperty('name', '')
+
+ root.setAttribute('name', 'test')
+ await waitForChanges()
+
+ expect(root.querySelector('input')).toHaveProperty('value', 'test')
+ expect(root.querySelector('input')).toHaveProperty('checked', true)
+ expect(root.querySelector('input')).toHaveProperty('name', 'test')
+
+ root.setAttribute('value', '')
+ await waitForChanges()
+
+ expect(root.querySelector('input')).toHaveProperty('value', '')
+ expect(root.querySelector('input')).toHaveProperty('checked', true)
+ expect(root.querySelector('input')).toHaveProperty('name', 'test')
+
+ root.dispatchEvent(new Event('click'))
+ await waitForChanges()
+
+ expect(root.querySelector('input')).toHaveProperty('value', '')
+ expect(root.querySelector('input')).toHaveProperty('checked', false)
+ expect(root.querySelector('input')).toHaveProperty('name', '')
+ })
})