fix(listbox): align setCheckedIndex behavior for multi and single choice

This commit is contained in:
jorenbroekema 2020-10-14 14:02:16 +02:00
parent 188fe50770
commit 8f4faee0c6
5 changed files with 61 additions and 20 deletions

View file

@ -648,7 +648,6 @@ export class LionCombobox extends OverlayMixin(LionListbox) {
this.opened = false; this.opened = false;
this.__shouldAutocompleteNextUpdate = true; this.__shouldAutocompleteNextUpdate = true;
this._setTextboxValue(''); this._setTextboxValue('');
// this.checkedIndex = -1;
break; break;
case 'Enter': case 'Enter':
if (!this.formElements[this.activeIndex]) { if (!this.formElements[this.activeIndex]) {

View file

@ -208,6 +208,42 @@ describe('lion-combobox', () => {
await el.updateComplete; await el.updateComplete;
expect(el._inputNode.value).to.equal('20'); expect(el._inputNode.value).to.equal('20');
}); });
it('sets modelValue to empty string if no option is selected', async () => {
const el = /** @type {LionCombobox} */ (await fixture(html`
<lion-combobox name="foo" .modelValue="${'Artichoke'}">
<lion-option .choiceValue="${'Artichoke'}">Artichoke</lion-option>
<lion-option .choiceValue="${'Chard'}">Chard</lion-option>
<lion-option .choiceValue="${'Chicory'}">Chicory</lion-option>
<lion-option .choiceValue="${'Victoria Plum'}">Victoria Plum</lion-option>
</lion-combobox>
`));
expect(el.modelValue).to.equal('Artichoke');
expect(el.formElements[0].checked).to.be.true;
el.checkedIndex = -1;
await el.updateComplete;
expect(el.modelValue).to.equal('');
expect(el.formElements[0].checked).to.be.false;
});
it('sets modelValue to empty array if no option is selected for multiple choice', async () => {
const el = /** @type {LionCombobox} */ (await fixture(html`
<lion-combobox name="foo" multiple-choice .modelValue="${['Artichoke']}">
<lion-option .choiceValue="${'Artichoke'}">Artichoke</lion-option>
<lion-option .choiceValue="${'Chard'}">Chard</lion-option>
<lion-option .choiceValue="${'Chicory'}">Chicory</lion-option>
<lion-option .choiceValue="${'Victoria Plum'}">Victoria Plum</lion-option>
</lion-combobox>
`));
expect(el.modelValue).to.eql(['Artichoke']);
expect(el.formElements[0].checked).to.be.true;
el.checkedIndex = [];
await el.updateComplete;
expect(el.modelValue).to.eql([]);
expect(el.formElements[0].checked).to.be.false;
});
}); });
describe('Listbox visibility', () => { describe('Listbox visibility', () => {

View file

@ -223,7 +223,7 @@ const ListboxMixinImplementation = superclass =>
* @deprecated * @deprecated
* This setter exists for backwards compatibility of single choice groups. * This setter exists for backwards compatibility of single choice groups.
* A setter api would be confusing for a multipleChoice group. Use `setCheckedIndex` instead. * A setter api would be confusing for a multipleChoice group. Use `setCheckedIndex` instead.
* @param {number} index * @param {number|number[]} index
*/ */
set checkedIndex(index) { set checkedIndex(index) {
this.setCheckedIndex(index); this.setCheckedIndex(index);
@ -338,23 +338,29 @@ const ListboxMixinImplementation = superclass =>
} }
/** /**
* When `multipleChoice` is false, will toggle, else will check provided index * If an array is passed for multiple-choice, it will check the indexes in array, and uncheck the rest
* @param {number} index * If a number is passed, the item with the passed index is checked without unchecking others
* @param {'set'|'unset'|'toggle'} multiMode * For single choice, __onChildCheckedChanged we ensure that we uncheck siblings
* @param {number|number[]} index
*/ */
setCheckedIndex(index, multiMode = 'toggle') { setCheckedIndex(index) {
if (this.formElements[index]) { if (this.multipleChoice && Array.isArray(index)) {
if (!this.multipleChoice) { this._uncheckChildren(this.formElements.filter(i => i === index));
this.formElements[index].checked = true; index.forEach(i => {
// In __onChildCheckedChanged, which also responds to programmatic (model)value changes if (this.formElements[i]) {
// of children, we do the rest (uncheck siblings) this.formElements[i].checked = true;
} else if (multiMode === 'toggle') { }
this.formElements[index].checked = !this.formElements[index].checked; });
} else { return;
this.formElements[index].checked = multiMode === 'set'; }
if (typeof index === 'number') {
if (index === -1) {
this._uncheckChildren();
}
if (this.formElements[index]) {
this.formElements[index].checked = true;
} }
} else if (!this.multipleChoice) {
this._uncheckChildren();
} }
} }

View file

@ -413,8 +413,8 @@ export function runListboxMixinSuite(customConfig = {}) {
<${optionTag} .choiceValue=${'30'} checked>Item 3</${optionTag}> <${optionTag} .choiceValue=${'30'} checked>Item 3</${optionTag}>
</${tag}> </${tag}>
`); `);
el.setCheckedIndex(2); el.setCheckedIndex(0);
expect(el.modelValue).to.deep.equal(['20']); expect(el.modelValue).to.deep.equal(['10', '20', '30']);
el.reset(); el.reset();
expect(el.modelValue).to.deep.equal(['20', '30']); expect(el.modelValue).to.deep.equal(['20', '30']);
}); });

View file

@ -39,7 +39,7 @@ export declare class ListboxHost {
public formElements: LionOption[]; public formElements: LionOption[];
public setCheckedIndex(index: number): void; public setCheckedIndex(index: number | number[]): void;
/** Reset interaction states and modelValue */ /** Reset interaction states and modelValue */
public reset(): void; public reset(): void;