Skip to content

Commit f9c5ffe

Browse files
author
swseverance
authored
fix(list): determine if option value changed (#19828) (#19870)
When the value of a `mat-list-option` is updated, the `mat-selection-list` `compareWith` function should be used to compare the new value with the old value. This prevents options from being incorrectly unselected when the option value is updated.
1 parent 134cbf3 commit f9c5ffe

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

src/material/list/selection-list.spec.ts

+47
Original file line numberDiff line numberDiff line change
@@ -814,6 +814,39 @@ describe('MatSelectionList without forms', () => {
814814
});
815815
});
816816

817+
describe('with changing option value', () => {
818+
let fixture: ComponentFixture<SelectionListWithChangingOptionValue>;
819+
let selectionList: MatSelectionList;
820+
let listOption: MatListOption;
821+
822+
beforeEach(async(() => {
823+
TestBed.configureTestingModule({
824+
imports: [MatListModule],
825+
declarations: [SelectionListWithChangingOptionValue],
826+
});
827+
828+
TestBed.compileComponents();
829+
}));
830+
831+
beforeEach(() => {
832+
fixture = TestBed.createComponent(SelectionListWithChangingOptionValue);
833+
fixture.detectChanges();
834+
835+
selectionList = fixture.debugElement.query(By.directive(MatSelectionList))!.componentInstance;
836+
listOption = fixture.debugElement.query(By.directive(MatListOption))!.componentInstance;
837+
});
838+
839+
it('should use `compareWith` function when updating option selection state', () => {
840+
expect(selectionList.selectedOptions.isSelected(listOption)).toBeTrue();
841+
fixture.componentInstance.value = {id: 1};
842+
fixture.detectChanges();
843+
expect(selectionList.selectedOptions.isSelected(listOption)).toBeTrue();
844+
fixture.componentInstance.value = {id: 2};
845+
fixture.detectChanges();
846+
expect(selectionList.selectedOptions.isSelected(listOption)).toBeFalse();
847+
});
848+
});
849+
817850
describe('with option disabled', () => {
818851
let fixture: ComponentFixture<SelectionListWithDisabledOption>;
819852
let listOptionEl: HTMLElement;
@@ -1678,6 +1711,20 @@ class SelectionListWithCustomComparator {
16781711
}
16791712

16801713

1714+
@Component({
1715+
template: `
1716+
<mat-selection-list [compareWith]="compareWith">
1717+
<mat-list-option [value]="value" [selected]="value.id === 1">
1718+
One
1719+
</mat-list-option>
1720+
</mat-selection-list>`
1721+
})
1722+
class SelectionListWithChangingOptionValue {
1723+
compareWith = (o1: any, o2: any) => o1 && o2 && o1.id === o2.id;
1724+
value = {id: 1};
1725+
}
1726+
1727+
16811728
@Component({
16821729
template: `
16831730
<mat-selection-list>

src/material/list/selection-list.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,11 @@ export class MatListOption extends _MatListOptionMixinBase implements AfterConte
145145
@Input()
146146
get value(): any { return this._value; }
147147
set value(newValue: any) {
148-
if (this.selected && newValue !== this.value && this._inputsInitialized) {
148+
if (
149+
this.selected &&
150+
!this.selectionList.compareWith(newValue, this.value) &&
151+
this._inputsInitialized
152+
) {
149153
this.selected = false;
150154
}
151155

0 commit comments

Comments
 (0)