diff --git a/.changeset/five-donuts-joke.md b/.changeset/five-donuts-joke.md new file mode 100644 index 000000000..19fd2b2ba --- /dev/null +++ b/.changeset/five-donuts-joke.md @@ -0,0 +1,5 @@ +--- +'@lion/select-rich': patch +--- + +The singleOption setting should only be true if there is exactly one option. This also needs to be true if there are dynamic additions or removals. diff --git a/packages/select-rich/README.md b/packages/select-rich/README.md index 42e44a041..adf957c07 100644 --- a/packages/select-rich/README.md +++ b/packages/select-rich/README.md @@ -9,7 +9,7 @@ Its implementation is based on the following Design pattern: ```js script -import { html } from '@lion/core'; +import { LitElement, html } from '@lion/core'; import { Required } from '@lion/form-core'; import { loadDefaultFeedbackMessages } from '@lion/validate-messages'; @@ -357,6 +357,55 @@ export const singleOption = () => html` `; ``` +When adding/removing options the `singleOption` will only be `true` when there is exactly one option. + +```js preview-story +class SingleOptionRemoveAdd extends LitElement { + static get properties() { + return { + options: { type: Array }, + }; + } + + constructor() { + super(); + this.options = ['Option 1']; + } + + render() { + return html` + + + + + ${this.options.map( + option => html` ${option} `, + )} + + + `; + } + + addOption() { + this.options.push(`Option ${this.options.length + 1}`); + this.options = [...this.options]; + this.requestUpdate(); + } + + removeOption() { + this.options.pop(); + this.options = [...this.options]; + this.requestUpdate(); + } +} + +customElements.define('single-option-remove-add', SingleOptionRemoveAdd); + +export const singleOptionRemoveAdd = () => { + return html``; +}; +``` + ### Custom Invoker You can provide a custom invoker using the invoker slot. diff --git a/packages/select-rich/src/LionSelectRich.js b/packages/select-rich/src/LionSelectRich.js index 9af059043..b9fd16651 100644 --- a/packages/select-rich/src/LionSelectRich.js +++ b/packages/select-rich/src/LionSelectRich.js @@ -159,16 +159,41 @@ export class LionSelectRich extends SlotMixin(ScopedElementsMixin(OverlayMixin(L this.initInteractionState(); } + /** + * @override + * @param {FormControl} child the child element (field) + * @param {number} indexToInsertAt index to insert the form element at + */ + addFormElement(child, indexToInsertAt) { + super.addFormElement(child, indexToInsertAt); + this._onFormElementsChanged(); + } + + /** + * @param {FormRegisteringHost} child the child element (field) + */ + removeFormElement(child) { + super.removeFormElement(child); + this._onFormElementsChanged(); + } + + _onFormElementsChanged() { + if (this.formElements.length === 1 && this.singleOption === false) { + this.singleOption = true; + this._invokerNode.singleOption = true; + } + if (this.formElements.length !== 1 && this.singleOption === true) { + this.singleOption = false; + this._invokerNode.singleOption = false; + } + } + /** * @param {import('lit-element').PropertyValues } changedProperties */ updated(changedProperties) { super.updated(changedProperties); - if (this.formElements.length === 1) { - this._invokerNode.singleOption = true; - } - if (changedProperties.has('disabled')) { if (this.disabled) { this._invokerNode.makeRequestToBeDisabled(); diff --git a/packages/select-rich/test/lion-select-rich.test.js b/packages/select-rich/test/lion-select-rich.test.js index ce10a1273..3153f0433 100644 --- a/packages/select-rich/test/lion-select-rich.test.js +++ b/packages/select-rich/test/lion-select-rich.test.js @@ -83,19 +83,6 @@ describe('lion-select-rich', () => { expect(el.hasAttribute('readonly')).to.be.true; expect(el._invokerNode.hasAttribute('readonly')).to.be.true; }); - - it('delegates singleOption to the invoker', async () => { - const el = await fixture(html` - - - Item 1 - - - `); - - expect(el.singleOption).to.be.true; - expect(el._invokerNode.hasAttribute('single-option')).to.be.true; - }); }); describe('overlay', () => { @@ -262,8 +249,8 @@ describe('lion-select-rich', () => { expect(el._overlayCtrl.inheritsReferenceWidth).to.equal('full'); }); - it('should set singleOption to true when options change dynamically to 1 option', async () => { - const elSingleoption = await fixture(html` + it('should have singleOption only if there is exactly one option', async () => { + const el = await fixture(html` Item 1 @@ -271,18 +258,23 @@ describe('lion-select-rich', () => { `); + expect(el.singleOption).to.be.false; + expect(el._invokerNode.singleOption).to.be.false; - elSingleoption._invokerNode.click(); - await elSingleoption.updateComplete; - expect(elSingleoption.singleOption).to.be.false; - - const optionELm = elSingleoption.querySelectorAll('lion-option')[0]; + const optionELm = el.querySelectorAll('lion-option')[0]; optionELm.parentNode.removeChild(optionELm); - elSingleoption.requestUpdate(); + el.requestUpdate(); + await el.updateComplete; + expect(el.singleOption).to.be.true; + expect(el._invokerNode.singleOption).to.be.true; - elSingleoption._invokerNode.click(); - await elSingleoption.updateComplete; - expect(elSingleoption.singleOption).to.be.true; + const newOption = document.createElement('lion-option'); + newOption.choiceValue = 30; + el._inputNode.appendChild(newOption); + el.requestUpdate(); + await el.updateComplete; + expect(el.singleOption).to.be.false; + expect(el._invokerNode.singleOption).to.be.false; }); });