diff --git a/src/controllers/itemSelection.ts b/src/controllers/itemSelection.ts index 8970e13..7ad1812 100644 --- a/src/controllers/itemSelection.ts +++ b/src/controllers/itemSelection.ts @@ -15,7 +15,7 @@ export class ItemSelectionController { * @return {T[]} */ public get selectedItems(): T[] { - return this.__items.filter((_item, idx) => this.__selectedIndices.has(idx)); + return this.items.filter((_item, idx) => this.__selectedIndices.has(idx)); } /** @@ -23,11 +23,15 @@ export class ItemSelectionController { * @return {T[]} */ public get items(): T[] { + if (this.__itemsGetter) { + return this.__itemsGetter(); + } return this.__items; } private __selectedIndices: Set = new Set(); private __items: T[] = []; + private __itemsGetter?: () => T[]; private __host: ReactiveControllerHost; private __options?: ItemSelectionOptions; @@ -38,11 +42,15 @@ export class ItemSelectionController { */ public constructor( host: ReactiveControllerHost, - items: T[], + items: T[] | (() => T[]), options?: ItemSelectionOptions ) { this.__host = host; - this.__items = items; + if (typeof items === 'function') { + this.__itemsGetter = items; + } else { + this.__items = items; + } if (options) { this.__options = options; @@ -99,6 +107,7 @@ export class ItemSelectionController { } const [currentSelection] = [...this.__selectedIndices]; + const items = this.items; let newIndex = 0; if (currentSelection !== undefined) { @@ -106,8 +115,8 @@ export class ItemSelectionController { if (newIndex < 0) { newIndex = 0; - } else if (newIndex >= this.__items.length) { - newIndex = this.__items.length - 1; + } else if (newIndex >= items.length) { + newIndex = items.length - 1; } } @@ -142,7 +151,9 @@ export class ItemSelectionController { throw new Error('selectAll() cannot be used when in single-select mode'); } - for (const item of this.__items) { + const items = this.items; + + for (const item of items) { this.select(item); } } @@ -185,7 +196,9 @@ export class ItemSelectionController { throw new Error('Index cannot be below 0'); } - if (idx >= this.__items.length) { + const items = this.items; + + if (idx >= items.length) { throw new Error('Index cannot be greater than size of items array'); } @@ -213,7 +226,7 @@ export class ItemSelectionController { * @return {void} */ public toggle(item: T, selected?: boolean): void { - const idx = this.__items.indexOf(item); + const idx = this.items.indexOf(item); if (idx === -1) { throw new Error('Item was not in items array'); diff --git a/src/test/controllers/itemSelection_test.ts b/src/test/controllers/itemSelection_test.ts index 3abea04..526902f 100644 --- a/src/test/controllers/itemSelection_test.ts +++ b/src/test/controllers/itemSelection_test.ts @@ -408,4 +408,18 @@ suite('ItemSelectionController', () => { assert.equal(element.shadowRoot!.textContent, 'Selected: b'); }); }); + + suite('with items function', () => { + setup(async () => { + const itemsFn = () => items; + controller = new ItemSelectionController(element, itemsFn); + element.controllers.push(controller as ReactiveController); + document.body.appendChild(element); + }); + + test('initialises to default selection', () => { + assert.is(controller.selectedItems.length, 0); + assert.is(controller.items, items); + }); + }); });