Skip to content

Commit c654589

Browse files
swseverancewagnermaciel
authored andcommitted
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. (cherry picked from commit f9c5ffe)
1 parent 1a44b4c commit c654589

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

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

Lines changed: 47 additions & 0 deletions
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

Lines changed: 5 additions & 1 deletion
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)