Skip to content

Commit ea700e6

Browse files
authored
fix(cdk-experimental/ui-patterns): add guardrails to selectOne for edge cases (angular#31402)
1 parent 5f47b22 commit ea700e6

File tree

4 files changed

+39
-2
lines changed

4 files changed

+39
-2
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/listbox/listbox.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -549,7 +549,7 @@ describe('Listbox Pattern', () => {
549549
listbox.onKeydown(down());
550550
expect(listbox.inputs.value()).toEqual(['Apricot']);
551551
listbox.onKeydown(down());
552-
expect(listbox.inputs.value()).toEqual([]);
552+
expect(listbox.inputs.value()).toEqual(['Apricot']);
553553
listbox.onKeydown(down());
554554
expect(listbox.inputs.value()).toEqual(['Blackberry']);
555555
});

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)