Skip to content

Commit

Permalink
fix(list): determine if option value changed (#19828) (#19870)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
swseverance committed Aug 20, 2020
1 parent 134cbf3 commit f9c5ffe
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 1 deletion.
47 changes: 47 additions & 0 deletions src/material/list/selection-list.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,39 @@ describe('MatSelectionList without forms', () => {
});
});

describe('with changing option value', () => {
let fixture: ComponentFixture<SelectionListWithChangingOptionValue>;
let selectionList: MatSelectionList;
let listOption: MatListOption;

beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [MatListModule],
declarations: [SelectionListWithChangingOptionValue],
});

TestBed.compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(SelectionListWithChangingOptionValue);
fixture.detectChanges();

selectionList = fixture.debugElement.query(By.directive(MatSelectionList))!.componentInstance;
listOption = fixture.debugElement.query(By.directive(MatListOption))!.componentInstance;
});

it('should use `compareWith` function when updating option selection state', () => {
expect(selectionList.selectedOptions.isSelected(listOption)).toBeTrue();
fixture.componentInstance.value = {id: 1};
fixture.detectChanges();
expect(selectionList.selectedOptions.isSelected(listOption)).toBeTrue();
fixture.componentInstance.value = {id: 2};
fixture.detectChanges();
expect(selectionList.selectedOptions.isSelected(listOption)).toBeFalse();
});
});

describe('with option disabled', () => {
let fixture: ComponentFixture<SelectionListWithDisabledOption>;
let listOptionEl: HTMLElement;
Expand Down Expand Up @@ -1678,6 +1711,20 @@ class SelectionListWithCustomComparator {
}


@Component({
template: `
<mat-selection-list [compareWith]="compareWith">
<mat-list-option [value]="value" [selected]="value.id === 1">
One
</mat-list-option>
</mat-selection-list>`
})
class SelectionListWithChangingOptionValue {
compareWith = (o1: any, o2: any) => o1 && o2 && o1.id === o2.id;
value = {id: 1};
}


@Component({
template: `
<mat-selection-list>
Expand Down
6 changes: 5 additions & 1 deletion src/material/list/selection-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,11 @@ export class MatListOption extends _MatListOptionMixinBase implements AfterConte
@Input()
get value(): any { return this._value; }
set value(newValue: any) {
if (this.selected && newValue !== this.value && this._inputsInitialized) {
if (
this.selected &&
!this.selectionList.compareWith(newValue, this.value) &&
this._inputsInitialized
) {
this.selected = false;
}

Expand Down

0 comments on commit f9c5ffe

Please sign in to comment.