diff --git a/src/lib/list/selection-list.spec.ts b/src/lib/list/selection-list.spec.ts
index 2315e69e03f..d76e7de7aac 100644
--- a/src/lib/list/selection-list.spec.ts
+++ b/src/lib/list/selection-list.spec.ts
@@ -5,7 +5,13 @@ import {
dispatchEvent,
dispatchKeyboardEvent,
} from '@angular/cdk/testing';
-import {Component, DebugElement, ChangeDetectionStrategy} from '@angular/core';
+import {
+ Component,
+ DebugElement,
+ ChangeDetectionStrategy,
+ QueryList,
+ ViewChildren,
+} from '@angular/core';
import {async, ComponentFixture, fakeAsync, TestBed, tick, flush} from '@angular/core/testing';
import {By} from '@angular/platform-browser';
import {
@@ -620,6 +626,7 @@ describe('MatSelectionList with forms', () => {
SelectionListWithPreselectedOption,
SelectionListWithPreselectedOptionAndModel,
SelectionListWithPreselectedFormControlOnPush,
+ SelectionListWithCustomComparator,
]
});
@@ -842,6 +849,24 @@ describe('MatSelectionList with forms', () => {
}));
});
+
+ describe('with custom compare function', () => {
+ it('should use a custom comparator to determine which options are selected', fakeAsync(() => {
+ const fixture = TestBed.createComponent(SelectionListWithCustomComparator);
+ const testComponent = fixture.componentInstance;
+
+ testComponent.compareWith = jasmine.createSpy('comparator', (o1, o2) => {
+ return o1 && o2 && o1.id === o2.id;
+ }).and.callThrough();
+
+ testComponent.selectedOptions = [{id: 2, label: 'Two'}];
+ fixture.detectChanges();
+ tick();
+
+ expect(testComponent.compareWith).toHaveBeenCalled();
+ expect(testComponent.optionInstances.toArray()[1].selected).toBe(true);
+ }));
+ });
});
@@ -1004,3 +1029,23 @@ class SelectionListWithPreselectedFormControlOnPush {
opts = ['opt1', 'opt2', 'opt3'];
formControl = new FormControl(['opt2']);
}
+
+
+@Component({
+ template: `
+
+
+ {{option.label}}
+
+ `
+})
+class SelectionListWithCustomComparator {
+ @ViewChildren(MatListOption) optionInstances: QueryList;
+ selectedOptions: {id: number, label: string}[] = [];
+ compareWith?: (o1: any, o2: any) => boolean;
+ options = [
+ {id: 1, label: 'One'},
+ {id: 2, label: 'Two'},
+ {id: 3, label: 'Three'}
+ ];
+}
diff --git a/src/lib/list/selection-list.ts b/src/lib/list/selection-list.ts
index 934fc41fe54..34843721688 100644
--- a/src/lib/list/selection-list.ts
+++ b/src/lib/list/selection-list.ts
@@ -279,6 +279,13 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
/** Tabindex of the selection list. */
@Input() tabIndex: number = 0;
+ /**
+ * Function used for comparing an option against the selected value when determining which
+ * options should appear as selected. The first argument is the value of an options. The second
+ * one is a value from the selected value. A boolean must be returned.
+ */
+ @Input() compareWith: (o1: any, o2: any) => boolean;
+
/** The currently selected options. */
selectedOptions: SelectionModel = new SelectionModel(true);
@@ -437,17 +444,15 @@ export class MatSelectionList extends _MatSelectionListMixinBase implements Focu
this._onTouched = fn;
}
- /** Returns the option with the specified value. */
- private _getOptionByValue(value: string): MatListOption | undefined {
- return this.options.find(option => option.value === value);
- }
-
/** Sets the selected options based on the specified values. */
private _setOptionsFromValues(values: string[]) {
this.options.forEach(option => option._setSelected(false));
values
- .map(value => this._getOptionByValue(value))
+ .map(value => {
+ return this.options.find(option =>
+ this.compareWith ? this.compareWith(option.value, value) : option.value === value);
+ })
.filter(Boolean)
.forEach(option => option!._setSelected(true));
}