diff --git a/packages/combobox/src/LionCombobox.js b/packages/combobox/src/LionCombobox.js index 02566c574..dfb7f18b4 100644 --- a/packages/combobox/src/LionCombobox.js +++ b/packages/combobox/src/LionCombobox.js @@ -648,7 +648,6 @@ export class LionCombobox extends OverlayMixin(LionListbox) { this.opened = false; this.__shouldAutocompleteNextUpdate = true; this._setTextboxValue(''); - // this.checkedIndex = -1; break; case 'Enter': if (!this.formElements[this.activeIndex]) { diff --git a/packages/combobox/test/lion-combobox.test.js b/packages/combobox/test/lion-combobox.test.js index 6995e569f..f174d7b53 100644 --- a/packages/combobox/test/lion-combobox.test.js +++ b/packages/combobox/test/lion-combobox.test.js @@ -208,6 +208,42 @@ describe('lion-combobox', () => { await el.updateComplete; 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` + + Artichoke + Chard + Chicory + Victoria Plum + + `)); + + 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` + + Artichoke + Chard + Chicory + Victoria Plum + + `)); + + 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', () => { diff --git a/packages/listbox/src/ListboxMixin.js b/packages/listbox/src/ListboxMixin.js index 8a50ff274..968e12a10 100644 --- a/packages/listbox/src/ListboxMixin.js +++ b/packages/listbox/src/ListboxMixin.js @@ -223,7 +223,7 @@ const ListboxMixinImplementation = superclass => * @deprecated * This setter exists for backwards compatibility of single choice groups. * A setter api would be confusing for a multipleChoice group. Use `setCheckedIndex` instead. - * @param {number} index + * @param {number|number[]} index */ set checkedIndex(index) { this.setCheckedIndex(index); @@ -338,23 +338,29 @@ const ListboxMixinImplementation = superclass => } /** - * When `multipleChoice` is false, will toggle, else will check provided index - * @param {number} index - * @param {'set'|'unset'|'toggle'} multiMode + * If an array is passed for multiple-choice, it will check the indexes in array, and uncheck the rest + * If a number is passed, the item with the passed index is checked without unchecking others + * For single choice, __onChildCheckedChanged we ensure that we uncheck siblings + * @param {number|number[]} index */ - setCheckedIndex(index, multiMode = 'toggle') { - if (this.formElements[index]) { - if (!this.multipleChoice) { - this.formElements[index].checked = true; - // In __onChildCheckedChanged, which also responds to programmatic (model)value changes - // of children, we do the rest (uncheck siblings) - } else if (multiMode === 'toggle') { - this.formElements[index].checked = !this.formElements[index].checked; - } else { - this.formElements[index].checked = multiMode === 'set'; + setCheckedIndex(index) { + if (this.multipleChoice && Array.isArray(index)) { + this._uncheckChildren(this.formElements.filter(i => i === index)); + index.forEach(i => { + if (this.formElements[i]) { + this.formElements[i].checked = true; + } + }); + return; + } + + if (typeof index === 'number') { + if (index === -1) { + this._uncheckChildren(); + } + if (this.formElements[index]) { + this.formElements[index].checked = true; } - } else if (!this.multipleChoice) { - this._uncheckChildren(); } } diff --git a/packages/listbox/test-suites/ListboxMixin.suite.js b/packages/listbox/test-suites/ListboxMixin.suite.js index a30ff4010..7a565a2ce 100644 --- a/packages/listbox/test-suites/ListboxMixin.suite.js +++ b/packages/listbox/test-suites/ListboxMixin.suite.js @@ -413,8 +413,8 @@ export function runListboxMixinSuite(customConfig = {}) { <${optionTag} .choiceValue=${'30'} checked>Item 3 `); - el.setCheckedIndex(2); - expect(el.modelValue).to.deep.equal(['20']); + el.setCheckedIndex(0); + expect(el.modelValue).to.deep.equal(['10', '20', '30']); el.reset(); expect(el.modelValue).to.deep.equal(['20', '30']); }); diff --git a/packages/listbox/types/ListboxMixinTypes.d.ts b/packages/listbox/types/ListboxMixinTypes.d.ts index de71c152d..4c6ddfecc 100644 --- a/packages/listbox/types/ListboxMixinTypes.d.ts +++ b/packages/listbox/types/ListboxMixinTypes.d.ts @@ -39,7 +39,7 @@ export declare class ListboxHost { public formElements: LionOption[]; - public setCheckedIndex(index: number): void; + public setCheckedIndex(index: number | number[]): void; /** Reset interaction states and modelValue */ public reset(): void;