diff --git a/src/liquid/components/ld-select/ld-select.tsx b/src/liquid/components/ld-select/ld-select.tsx index f8214495bd..1a8eb9872a 100644 --- a/src/liquid/components/ld-select/ld-select.tsx +++ b/src/liquid/components/ld-select/ld-select.tsx @@ -103,7 +103,6 @@ export class LdSelect { @State() hasMore = false @State() hasCustomIcon = false @State() renderHiddenInput = false - @State() ignoreSlotChanges = false @Watch('selected') emitEventsAndUpdateHidden( @@ -335,11 +334,6 @@ export class LdSelect { } private initOptions() { - this.ignoreSlotChanges = true - setTimeout(() => { - this.ignoreSlotChanges = false - }) - const initialized = this.initialized let children if (!initialized) { @@ -387,8 +381,8 @@ export class LdSelect { } this.internalOptionsHTML = internalOptionsHTML } - this.selected = selectedChildren.map((child) => ({ - value: child.getAttribute('value'), + this.selected = selectedChildren.map((child: HTMLLdOptionElement) => ({ + value: child.value, text: child.innerText, })) @@ -432,8 +426,6 @@ export class LdSelect { } private handleSlotChange(mutationsList: MutationRecord[]) { - if (this.ignoreSlotChanges) return - if ( mutationsList.some( (record) => (record.target as HTMLElement).tagName !== 'LD-OPTION' diff --git a/src/liquid/components/ld-select/test/__snapshots__/ld-select.spec.ts.snap b/src/liquid/components/ld-select/test/__snapshots__/ld-select.spec.ts.snap index e96e6e3992..05ab2be132 100644 --- a/src/liquid/components/ld-select/test/__snapshots__/ld-select.spec.ts.snap +++ b/src/liquid/components/ld-select/test/__snapshots__/ld-select.spec.ts.snap @@ -77,7 +77,107 @@ exports[`ld-select creates hidden input field, if inside a form 1`] = ` `; -exports[`ld-select fills hidden input fields with initially selected option values 1`] = ` +exports[`ld-select observes slot content changes and updates internal options in popper and hidden input fields 1`] = ` + +
+ + +
+ +
+ +
+
+ +
+ + +
+
+ +
+
+
+
+
+ + +
+ + + + + + +
+
+ Apple +
+ + +
+ + + + + + +
+
+ Pear +
+ + +
+ + + + + + +
+
+ Banana +
+
+
+
+
+ + + + + Apple + + + + + + Pear + + + + + + Banana + + +
+
+ +`; + +exports[`ld-select renders initially selected options as internal options and hidden input fields 1`] = `
@@ -193,51 +293,148 @@ exports[`ld-select fills hidden input fields with initially selected option valu `; -exports[`ld-select updates hidden input fields 1`] = ` - - -
- -
- -
-
-
- - - Pick a fruit - - - - - - +exports[`ld-select updates internal options in popper and hidden input fields 1`] = ` + +
+ + +
+ +
+ +
+
+
+
    +
  • + +
  • +
  • + +
  • +
+ + + + + +
+
+
+
+
-
-
+ + + + + + Apple + + + + + + Pear + + + + + + Banana + + + + + +
+ + +
+
+ +
-
-
- - - - Apple - - - - - - Pear - - - - - - Banana - - - -
+
+ + +
+ + + + +
+
+ Apple +
+ + +
+ + + + +
+
+ Pear +
+ + +
+ + + + +
+
+ Banana +
+
+
+
+
+ + `; diff --git a/src/liquid/components/ld-select/test/ld-select.spec.ts b/src/liquid/components/ld-select/test/ld-select.spec.ts index b32044f5e9..f584caa644 100644 --- a/src/liquid/components/ld-select/test/ld-select.spec.ts +++ b/src/liquid/components/ld-select/test/ld-select.spec.ts @@ -16,7 +16,14 @@ const components = [ LdTheme, ] -global.MutationObserver = MutationObserver +let triggerableMutationObserver +const TriggerableMutationObserver = function (cb) { + triggerableMutationObserver = new MutationObserver(cb) + triggerableMutationObserver.trigger = cb + return triggerableMutationObserver +} + +global.MutationObserver = TriggerableMutationObserver as MutationObserver class FocusManager { focus(el) { @@ -322,32 +329,6 @@ describe('ld-select', () => { ) }) - it('ignores slot changes if options are being initialized', async () => { - expect.assertions(1) - const ldSelect = new LdSelect() - - try { - ldSelect.ignoreSlotChanges = true - ;((ldSelect as unknown) as { - handleSlotChange: () => void - }).handleSlotChange() - } catch (err) { - // the following assertion should be skipped. - expect(err).toStrictEqual(Error('should be skipped.')) - } - - try { - ldSelect.ignoreSlotChanges = false - ;((ldSelect as unknown) as { - handleSlotChange: () => void - }).handleSlotChange() - } catch (err) { - expect(err).toStrictEqual( - TypeError("Cannot read property 'some' of undefined") - ) - } - }) - it('deselects a selected option if another option is selected in single select mode', async () => { const page = await newSpecPage({ components, @@ -1922,7 +1903,7 @@ describe('ld-select', () => { expect(page.root).toMatchSnapshot() }) - it('fills hidden input fields with initially selected option values', async () => { + it('renders initially selected options as internal options and hidden input fields', async () => { const page = await newSpecPage({ components, html: ` @@ -1960,7 +1941,7 @@ describe('ld-select', () => { } }) - it('updates hidden input fields', async () => { + it('updates internal options in popper and hidden input fields', async () => { const page = await newSpecPage({ components, html: ` @@ -1974,16 +1955,47 @@ describe('ld-select', () => { `, }) - const ldSelect = page.root await triggerPopperWithClick(page) const { internalOptions } = await getInternalOptions(page) - const [option1, option2, option3] = internalOptions + const [option0, option1, option2] = internalOptions + option0.click() option1.click() option2.click() - option3.click() - option1.click() // deselect + option0.click() // deselect + + await page.waitForChanges() + + expect(page.body).toMatchSnapshot() + }) + + it('observes slot content changes and updates internal options in popper and hidden input fields', async () => { + const page = await newSpecPage({ + components, + html: ` +
+ + Apple + Pear + Banana + +
+ `, + }) + const ldSelect = page.root + + jest.advanceTimersByTime(0) + await page.waitForChanges() + + const slottedOptions = ldSelect.querySelectorAll('ld-option') + expect(slottedOptions.length).toEqual(3) + + slottedOptions[2].setAttribute('selected', '') + await page.waitForChanges() + triggerableMutationObserver.trigger([]) + + await page.waitForChanges() - expect(ldSelect).toMatchSnapshot() + expect(page.body).toMatchSnapshot() }) })