@@ -15,6 +15,7 @@ import {combineLatest} from 'rxjs/operators/combineLatest';
1515import { map } from 'rxjs/operators/map' ;
1616import { startWith } from 'rxjs/operators/startWith' ;
1717import { empty } from 'rxjs/observable/empty' ;
18+ import { isNumberValue } from '@angular/cdk/coercion' ;
1819
1920/**
2021 * Data source that accepts a client-side data array and includes native support of filtering,
@@ -88,7 +89,8 @@ export class MatTableDataSource<T> implements DataSource<T> {
8889 private _paginator : MatPaginator | null ;
8990
9091 /**
91- * Data accessor function that is used for accessing data properties for sorting.
92+ * Data accessor function that is used for accessing data properties for sorting through
93+ * the default sortPredicate.
9294 * This default function assumes that the sort header IDs (which defaults to the column name)
9395 * matches the data's properties (e.g. column Xyz represents data['Xyz']).
9496 * May be set to a custom function for different behavior.
@@ -97,22 +99,46 @@ export class MatTableDataSource<T> implements DataSource<T> {
9799 */
98100 sortingDataAccessor : ( ( data : T , sortHeaderId : string ) => string | number ) =
99101 ( data : T , sortHeaderId : string ) : string | number => {
100- const value : any = data [ sortHeaderId ] ;
102+ let value : any = data [ sortHeaderId ] ;
103+ return isNumberValue ( value ) ? Number ( value ) : value ;
104+ }
101105
102- // If the value is a string and only whitespace, return the value.
103- // Otherwise +value will convert it to 0.
104- if ( typeof value === 'string' && ! value . trim ( ) ) {
105- return value ;
106- }
106+ /**
107+ * Returns a sorted array of the provided data according to the state of the MatSort. Called
108+ * after changes are made to the filtered data or when sort changes are emitted from MatSort.
109+ * By default, the function retrieves the active sort and its direction and compares data
110+ * by retrieving data using the sortingDataAccessor. May be overridden for a custom implementation
111+ * of data ordering.
112+ * @param data The array of data that should be sorted.
113+ * @param sort The connected MatSort that holds the current sort state.
114+ */
115+ sortPredicate : ( ( data : T [ ] , sort : MatSort ) => T [ ] ) = ( data : T [ ] , sort : MatSort ) : T [ ] => {
116+ const active = sort . active ;
117+ const direction = sort . direction ;
118+ if ( ! active || direction == '' ) { return data ; }
119+
120+ return data . sort ( ( a , b ) => {
121+ let valueA = this . sortingDataAccessor ( a , active ) ;
122+ let valueB = this . sortingDataAccessor ( b , active ) ;
107123
108- return isNaN ( + value ) ? value : + value ;
124+ let comparatorResult = 0 ;
125+ if ( valueA && valueB ) {
126+ comparatorResult = valueA < valueB ? - 1 : 1 ;
127+ } else if ( valueA ) {
128+ comparatorResult = 1 ;
129+ } else if ( valueB ) {
130+ comparatorResult = - 1 ;
131+ }
132+
133+ return comparatorResult * ( direction == 'asc' ? 1 : - 1 ) ;
134+ } ) ;
109135 }
110136
111137 /**
112138 * Checks if a data object matches the data source's filter string. By default, each data object
113139 * is converted to a string of its properties and returns true if the filter has
114140 * at least one occurrence in that string. By default, the filter string has its whitespace
115- * trimmed and the match is case-insensitive. May be overriden for a custom implementation of
141+ * trimmed and the match is case-insensitive. May be overridden for a custom implementation of
116142 * filter matching.
117143 * @param data Data object used to check against the filter.
118144 * @param filter Filter string that has been set on the data source.
@@ -172,7 +198,7 @@ export class MatTableDataSource<T> implements DataSource<T> {
172198 _filterData ( data : T [ ] ) {
173199 // If there is a filter string, filter out data that does not contain it.
174200 // Each data object is converted to a string using the function defined by filterTermAccessor.
175- // May be overriden for customization.
201+ // May be overridden for customization.
176202 this . filteredData =
177203 ! this . filter ? data : data . filter ( obj => this . filterPredicate ( obj , this . filter ) ) ;
178204
@@ -188,16 +214,9 @@ export class MatTableDataSource<T> implements DataSource<T> {
188214 */
189215 _orderData ( data : T [ ] ) : T [ ] {
190216 // If there is no active sort or direction, return the data without trying to sort.
191- if ( ! this . sort || ! this . sort . active || this . sort . direction == '' ) { return data ; }
192-
193- const active = this . sort . active ;
194- const direction = this . sort . direction ;
217+ if ( ! this . sort ) { return data ; }
195218
196- return data . slice ( ) . sort ( ( a , b ) => {
197- let valueA = this . sortingDataAccessor ( a , active ) ;
198- let valueB = this . sortingDataAccessor ( b , active ) ;
199- return ( valueA < valueB ? - 1 : 1 ) * ( direction == 'asc' ? 1 : - 1 ) ;
200- } ) ;
219+ return this . sortPredicate ( data . slice ( ) , this . sort ) ;
201220 }
202221
203222 /**
0 commit comments