Skip to content

Commit d54a75a

Browse files
crisbetojosephperrott
authored andcommitted
feat(select): allow for option sorting logic to be customized (#11890)
1 parent d6ca3ec commit d54a75a

File tree

2 files changed

+39
-4
lines changed

2 files changed

+39
-4
lines changed

src/lib/select/select.spec.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3850,6 +3850,29 @@ describe('MatSelect', () => {
38503850
expect(fixture.componentInstance.control.value).toEqual(['steak-0', 'pizza-1', 'tacos-2']);
38513851
}));
38523852

3853+
it('should be able to customize the value sorting logic', fakeAsync(() => {
3854+
fixture.componentInstance.sortComparator = (a, b, optionsArray) => {
3855+
return optionsArray.indexOf(b) - optionsArray.indexOf(a);
3856+
};
3857+
fixture.detectChanges();
3858+
3859+
trigger.click();
3860+
fixture.detectChanges();
3861+
flush();
3862+
3863+
const options = overlayContainerElement.querySelectorAll('mat-option') as
3864+
NodeListOf<HTMLElement>;
3865+
3866+
for (let i = 0; i < 3; i++) {
3867+
options[i].click();
3868+
}
3869+
fixture.detectChanges();
3870+
3871+
// Expect the items to be in reverse order.
3872+
expect(trigger.textContent).toContain('Tacos, Pizza, Steak');
3873+
expect(fixture.componentInstance.control.value).toEqual(['tacos-2', 'pizza-1', 'steak-0']);
3874+
}));
3875+
38533876
it('should sort the values that get set via the model based on the panel order',
38543877
fakeAsync(() => {
38553878
trigger.click();
@@ -4320,7 +4343,8 @@ class FloatLabelSelect {
43204343
selector: 'multi-select',
43214344
template: `
43224345
<mat-form-field>
4323-
<mat-select multiple placeholder="Food" [formControl]="control">
4346+
<mat-select multiple placeholder="Food" [formControl]="control"
4347+
[sortComparator]="sortComparator">
43244348
<mat-option *ngFor="let food of foods"
43254349
[value]="food.value">{{ food.viewValue }}
43264350
</mat-option>
@@ -4343,6 +4367,7 @@ class MultiSelect {
43434367

43444368
@ViewChild(MatSelect) select: MatSelect;
43454369
@ViewChildren(MatOption) options: QueryList<MatOption>;
4370+
sortComparator: (a: MatOption, b: MatOption, options: MatOption[]) => number;
43464371
}
43474372

43484373
@Component({

src/lib/select/select.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
382382
}
383383

384384
/**
385-
* A function to compare the option values with the selected values. The first argument
385+
* Function to compare the option values with the selected values. The first argument
386386
* is a value from an option. The second is a value from the selection. A boolean
387387
* should be returned.
388388
*/
@@ -416,9 +416,15 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
416416
/** Input that can be used to specify the `aria-labelledby` attribute. */
417417
@Input('aria-labelledby') ariaLabelledby: string;
418418

419-
/** An object used to control when error messages are shown. */
419+
/** Object used to control when error messages are shown. */
420420
@Input() errorStateMatcher: ErrorStateMatcher;
421421

422+
/**
423+
* Function used to sort the values in a select in multiple mode.
424+
* Follows the same logic as `Array.prototype.sort`.
425+
*/
426+
@Input() sortComparator: (a: MatOption, b: MatOption, options: MatOption[]) => number;
427+
422428
/** Unique id of the element. */
423429
@Input()
424430
get id(): string { return this._id; }
@@ -920,7 +926,11 @@ export class MatSelect extends _MatSelectMixinBase implements AfterContentInit,
920926
private _sortValues() {
921927
if (this.multiple) {
922928
const options = this.options.toArray();
923-
this._selectionModel.sort((a, b) => options.indexOf(a) - options.indexOf(b));
929+
930+
this._selectionModel.sort((a, b) => {
931+
return this.sortComparator ? this.sortComparator(a, b, options) :
932+
options.indexOf(a) - options.indexOf(b);
933+
});
924934
this.stateChanges.next();
925935
}
926936
}

0 commit comments

Comments
 (0)