Skip to content

Commit a079034

Browse files
committed
fix(cdk-experimental/ui-patterns): add guardrails to selectOne for edge cases
1 parent 15e9a57 commit a079034

File tree

3 files changed

+38
-1
lines changed

3 files changed

+38
-1
lines changed

src/cdk-experimental/ui-patterns/behaviors/list-selection/list-selection.spec.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,34 @@ describe('List Selection', () => {
219219
selection.selectOne(); // [0]
220220
expect(selection.inputs.value()).toEqual([0]);
221221
});
222+
223+
it('should do nothing if the current active item is disabled', () => {
224+
const selection = getSelection({multi: signal(true)});
225+
const items = selection.inputs.items() as TestItem[];
226+
227+
selection.inputs.focusManager.focus(items[1]);
228+
selection.select();
229+
expect(selection.inputs.value()).toEqual([1]);
230+
231+
selection.inputs.focusManager.focus(items[0]);
232+
items[0].disabled.set(true);
233+
selection.selectOne();
234+
expect(selection.inputs.value()).toEqual([1]);
235+
});
236+
237+
it('should not select an item if the list is not multiselectable and not all items are deselected', () => {
238+
const selection = getSelection({multi: signal(false)});
239+
const items = selection.inputs.items() as TestItem[];
240+
241+
selection.inputs.focusManager.focus(items[1]);
242+
selection.select();
243+
expect(selection.inputs.value()).toEqual([1]);
244+
245+
items[1].disabled.set(true);
246+
selection.inputs.focusManager.focus(items[2]);
247+
selection.selectOne();
248+
expect(selection.inputs.value()).toEqual([1]);
249+
});
222250
});
223251

224252
describe('#selectRange', () => {

src/cdk-experimental/ui-patterns/behaviors/list-selection/list-selection.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,16 @@ export class ListSelection<T extends ListSelectionItem<V>, V> {
120120

121121
/** Sets the selection to only the current active item. */
122122
selectOne() {
123+
if (this.inputs.focusManager.activeItem().disabled()) {
124+
return;
125+
}
126+
123127
this.deselectAll();
128+
129+
if (this.inputs.value().length > 0 && !this.inputs.multi()) {
130+
return;
131+
}
132+
124133
this.select();
125134
}
126135

src/cdk-experimental/ui-patterns/tabs/tabs.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ export class TabListPattern {
289289

290290
/** Handles updating selection for the tablist. */
291291
private _select(opts?: SelectOptions) {
292-
if (opts?.select && !this.focusManager.activeItem().disabled()) {
292+
if (opts?.select) {
293293
this.selection.selectOne();
294294
this.expansionManager.open(this.focusManager.activeItem());
295295
}

0 commit comments

Comments
 (0)