-
Notifications
You must be signed in to change notification settings - Fork 6.8k
/
Copy pathsort.ts
171 lines (144 loc) · 5.45 KB
/
sort.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/**
* @license
* Copyright Google LLC All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {
Directive,
EventEmitter,
Input,
isDevMode,
OnChanges,
OnDestroy,
OnInit,
Output,
} from '@angular/core';
import {coerceBooleanProperty} from '@angular/cdk/coercion';
import {CanDisable, HasInitialized, mixinDisabled, mixinInitialized} from '@angular/material/core';
import {SortDirection} from './sort-direction';
import {
getSortDuplicateSortableIdError,
getSortHeaderMissingIdError,
getSortInvalidDirectionError
} from './sort-errors';
import {Subject} from 'rxjs';
/** Interface for a directive that holds sorting state consumed by `MatSortHeader`. */
export interface MatSortable {
/** The id of the column being sorted. */
id: string;
/** Starting sort direction. */
start: 'asc' | 'desc';
/** Whether to disable clearing the sorting state. */
disableClear: boolean;
}
/** The current sort state. */
export interface Sort {
/** The id of the column being sorted. */
active: string;
/** The sort direction. */
direction: SortDirection;
}
// Boilerplate for applying mixins to MatSort.
/** @docs-private */
export class MatSortBase {}
export const _MatSortMixinBase = mixinInitialized(mixinDisabled(MatSortBase));
/** Container for MatSortables to manage the sort state and provide default sort parameters. */
@Directive({
selector: '[matSort]',
exportAs: 'matSort',
inputs: ['disabled: matSortDisabled']
})
export class MatSort extends _MatSortMixinBase
implements CanDisable, HasInitialized, OnChanges, OnDestroy, OnInit {
/** Collection of all registered sortables that this directive manages. */
sortables = new Map<string, MatSortable>();
/** Used to notify any child components listening to state changes. */
readonly _stateChanges = new Subject<void>();
/** The id of the most recently sorted MatSortable. */
@Input('matSortActive') active: string;
/**
* The direction to set when an MatSortable is initially sorted.
* May be overriden by the MatSortable's sort start.
*/
@Input('matSortStart') start: 'asc' | 'desc' = 'asc';
/** The sort direction of the currently active MatSortable. */
@Input('matSortDirection')
get direction(): SortDirection { return this._direction; }
set direction(direction: SortDirection) {
if (isDevMode() && direction && direction !== 'asc' && direction !== 'desc') {
throw getSortInvalidDirectionError(direction);
}
this._direction = direction;
}
private _direction: SortDirection = '';
/**
* Whether to disable the user from clearing the sort by finishing the sort direction cycle.
* May be overriden by the MatSortable's disable clear input.
*/
@Input('matSortDisableClear')
get disableClear(): boolean { return this._disableClear; }
set disableClear(v: boolean) { this._disableClear = coerceBooleanProperty(v); }
private _disableClear: boolean;
/** Event emitted when the user changes either the active sort or sort direction. */
@Output('matSortChange') readonly sortChange: EventEmitter<Sort> = new EventEmitter<Sort>();
/**
* Register function to be used by the contained MatSortables. Adds the MatSortable to the
* collection of MatSortables.
*/
register(sortable: MatSortable): void {
if (!sortable.id) {
throw getSortHeaderMissingIdError();
}
if (this.sortables.has(sortable.id)) {
throw getSortDuplicateSortableIdError(sortable.id);
}
this.sortables.set(sortable.id, sortable);
}
/**
* Unregister function to be used by the contained MatSortables. Removes the MatSortable from the
* collection of contained MatSortables.
*/
deregister(sortable: MatSortable): void {
this.sortables.delete(sortable.id);
}
/** Sets the active sort id and determines the new sort direction. */
sort(sortable: MatSortable): void {
if (this.active != sortable.id) {
this.active = sortable.id;
this.direction = sortable.start ? sortable.start : this.start;
} else {
this.direction = this.getNextSortDirection(sortable);
}
this.sortChange.emit({active: this.active, direction: this.direction});
}
/** Returns the next sort direction of the active sortable, checking for potential overrides. */
getNextSortDirection(sortable: MatSortable): SortDirection {
if (!sortable) { return ''; }
// Get the sort direction cycle with the potential sortable overrides.
const disableClear = sortable.disableClear != null ? sortable.disableClear : this.disableClear;
let sortDirectionCycle = getSortDirectionCycle(sortable.start || this.start, disableClear);
// Get and return the next direction in the cycle
let nextDirectionIndex = sortDirectionCycle.indexOf(this.direction) + 1;
if (nextDirectionIndex >= sortDirectionCycle.length) { nextDirectionIndex = 0; }
return sortDirectionCycle[nextDirectionIndex];
}
ngOnInit() {
this._markInitialized();
}
ngOnChanges() {
this._stateChanges.next();
}
ngOnDestroy() {
this._stateChanges.complete();
}
}
/** Returns the sort direction cycle to use given the provided parameters of order and clear. */
function getSortDirectionCycle(start: 'asc' | 'desc',
disableClear: boolean): SortDirection[] {
let sortOrder: SortDirection[] = ['asc', 'desc'];
if (start == 'desc') { sortOrder.reverse(); }
if (!disableClear) { sortOrder.push(''); }
return sortOrder;
}