fix(select-rich): singleOption true only if there is exactly one option
This commit is contained in:
parent
857206548c
commit
e2d772f5b3
4 changed files with 100 additions and 29 deletions
5
.changeset/five-donuts-joke.md
Normal file
5
.changeset/five-donuts-joke.md
Normal file
|
|
@ -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.
|
||||||
|
|
@ -9,7 +9,7 @@ Its implementation is based on the following Design pattern:
|
||||||
<https://www.w3.org/TR/wai-aria-practices/examples/listbox/listbox-collapsible.html>
|
<https://www.w3.org/TR/wai-aria-practices/examples/listbox/listbox-collapsible.html>
|
||||||
|
|
||||||
```js script
|
```js script
|
||||||
import { html } from '@lion/core';
|
import { LitElement, html } from '@lion/core';
|
||||||
import { Required } from '@lion/form-core';
|
import { Required } from '@lion/form-core';
|
||||||
import { loadDefaultFeedbackMessages } from '@lion/validate-messages';
|
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`
|
||||||
|
<button @click=${this.addOption}>Add an option</button>
|
||||||
|
<button @click=${this.removeOption}>Remove last option</button>
|
||||||
|
<lion-select-rich name="favoriteColor" label="Favorite color">
|
||||||
|
<lion-options slot="input">
|
||||||
|
${this.options.map(
|
||||||
|
option => html` <lion-option .choiceValue=${option}>${option}</lion-option> `,
|
||||||
|
)}
|
||||||
|
</lion-options>
|
||||||
|
</lion-select-rich>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
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`<single-option-remove-add></single-option-remove-add>`;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
### Custom Invoker
|
### Custom Invoker
|
||||||
|
|
||||||
You can provide a custom invoker using the invoker slot.
|
You can provide a custom invoker using the invoker slot.
|
||||||
|
|
|
||||||
|
|
@ -159,16 +159,41 @@ export class LionSelectRich extends SlotMixin(ScopedElementsMixin(OverlayMixin(L
|
||||||
this.initInteractionState();
|
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
|
* @param {import('lit-element').PropertyValues } changedProperties
|
||||||
*/
|
*/
|
||||||
updated(changedProperties) {
|
updated(changedProperties) {
|
||||||
super.updated(changedProperties);
|
super.updated(changedProperties);
|
||||||
|
|
||||||
if (this.formElements.length === 1) {
|
|
||||||
this._invokerNode.singleOption = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changedProperties.has('disabled')) {
|
if (changedProperties.has('disabled')) {
|
||||||
if (this.disabled) {
|
if (this.disabled) {
|
||||||
this._invokerNode.makeRequestToBeDisabled();
|
this._invokerNode.makeRequestToBeDisabled();
|
||||||
|
|
|
||||||
|
|
@ -83,19 +83,6 @@ describe('lion-select-rich', () => {
|
||||||
expect(el.hasAttribute('readonly')).to.be.true;
|
expect(el.hasAttribute('readonly')).to.be.true;
|
||||||
expect(el._invokerNode.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`
|
|
||||||
<lion-select-rich>
|
|
||||||
<lion-options slot="input">
|
|
||||||
<lion-option .choiceValue=${10}>Item 1</lion-option>
|
|
||||||
</lion-options>
|
|
||||||
</lion-select-rich>
|
|
||||||
`);
|
|
||||||
|
|
||||||
expect(el.singleOption).to.be.true;
|
|
||||||
expect(el._invokerNode.hasAttribute('single-option')).to.be.true;
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('overlay', () => {
|
describe('overlay', () => {
|
||||||
|
|
@ -262,8 +249,8 @@ describe('lion-select-rich', () => {
|
||||||
expect(el._overlayCtrl.inheritsReferenceWidth).to.equal('full');
|
expect(el._overlayCtrl.inheritsReferenceWidth).to.equal('full');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set singleOption to true when options change dynamically to 1 option', async () => {
|
it('should have singleOption only if there is exactly one option', async () => {
|
||||||
const elSingleoption = await fixture(html`
|
const el = await fixture(html`
|
||||||
<lion-select-rich>
|
<lion-select-rich>
|
||||||
<lion-options slot="input">
|
<lion-options slot="input">
|
||||||
<lion-option .choiceValue=${10}>Item 1</lion-option>
|
<lion-option .choiceValue=${10}>Item 1</lion-option>
|
||||||
|
|
@ -271,18 +258,23 @@ describe('lion-select-rich', () => {
|
||||||
</lion-options>
|
</lion-options>
|
||||||
</lion-select-rich>
|
</lion-select-rich>
|
||||||
`);
|
`);
|
||||||
|
expect(el.singleOption).to.be.false;
|
||||||
|
expect(el._invokerNode.singleOption).to.be.false;
|
||||||
|
|
||||||
elSingleoption._invokerNode.click();
|
const optionELm = el.querySelectorAll('lion-option')[0];
|
||||||
await elSingleoption.updateComplete;
|
|
||||||
expect(elSingleoption.singleOption).to.be.false;
|
|
||||||
|
|
||||||
const optionELm = elSingleoption.querySelectorAll('lion-option')[0];
|
|
||||||
optionELm.parentNode.removeChild(optionELm);
|
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();
|
const newOption = document.createElement('lion-option');
|
||||||
await elSingleoption.updateComplete;
|
newOption.choiceValue = 30;
|
||||||
expect(elSingleoption.singleOption).to.be.true;
|
el._inputNode.appendChild(newOption);
|
||||||
|
el.requestUpdate();
|
||||||
|
await el.updateComplete;
|
||||||
|
expect(el.singleOption).to.be.false;
|
||||||
|
expect(el._invokerNode.singleOption).to.be.false;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue