Skip to content

Commit 0a654e9

Browse files
committed
feat(table): add MatTableDataSource
1 parent ac70420 commit 0a654e9

File tree

9 files changed

+617
-40
lines changed

9 files changed

+617
-40
lines changed

src/cdk/rxjs/rx-operators.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {Observable, ObservableInput} from 'rxjs/Observable';
9+
// Subscribable needs to be imported because combineLatest has or is using it, but it does not need
10+
// to be used in any of the explicit typings in this file.
11+
// tslint:disable-next-line:no-unused-variable
12+
import {Observable, ObservableInput, Subscribable} from 'rxjs/Observable';
1013
import {PartialObserver} from 'rxjs/Observer';
1114
import {Subscription} from 'rxjs/Subscription';
1215
import {IScheduler} from 'rxjs/Scheduler';
@@ -22,6 +25,7 @@ import {startWith as startWithOperator} from 'rxjs/operator/startWith';
2225
import {debounceTime as debounceTimeOperator} from 'rxjs/operator/debounceTime';
2326
import {auditTime as auditTimeOperator} from 'rxjs/operator/auditTime';
2427
import {takeUntil as takeUntilOperator} from 'rxjs/operator/takeUntil';
28+
import {combineLatest as combineLatestOperator} from 'rxjs/operator/combineLatest';
2529

2630
/**
2731
* Represents a strongly-typed chain of RxJS operators.
@@ -71,6 +75,9 @@ export interface StrictRxChain<T> {
7175

7276
call(operator: takeUntilOperatorType<T>, notifier: Observable<any>): StrictRxChain<T>;
7377

78+
call<T2>(operator: combineLatestOperatorType<T, T2>,
79+
v2: ObservableInput<T2>): StrictRxChain<[T, T2]>;
80+
7481
subscribe(fn: (t: T) => void): Subscription;
7582

7683
result(): Observable<T>;
@@ -89,6 +96,7 @@ export class StartWithBrand { private _; }
8996
export class DebounceTimeBrand { private _; }
9097
export class AuditTimeBrand { private _; }
9198
export class TakeUntilBrand { private _; }
99+
export class CombineLatestBrand { private _; }
92100
/* tslint:enable:no-unused-variable */
93101

94102

@@ -104,8 +112,9 @@ export type startWithOperatorType<T> = typeof startWithOperator & StartWithBrand
104112
export type debounceTimeOperatorType<T> = typeof debounceTimeOperator & DebounceTimeBrand;
105113
export type auditTimeOperatorType<T> = typeof auditTimeOperator & AuditTimeBrand;
106114
export type takeUntilOperatorType<T> = typeof takeUntilOperator & TakeUntilBrand;
115+
export type combineLatestOperatorType<T, R> = typeof combineLatestOperator & CombineLatestBrand;
107116

108-
// We add `Function` to the type intersection to make this nomically different from
117+
// We add `Function` to the type intersection to make this nominally different from
109118
// `finallyOperatorType` while still being structurally the same. Without this, TypeScript tries to
110119
// reduce `typeof _finallyOperator & FinallyBrand` to `finallyOperatorType<T>` and then fails
111120
// because `T` isn't known.
@@ -123,3 +132,5 @@ export const debounceTime =
123132
debounceTimeOperator as typeof debounceTimeOperator & DebounceTimeBrand & Function;
124133
export const auditTime = auditTimeOperator as typeof auditTimeOperator & AuditTimeBrand & Function;
125134
export const takeUntil = takeUntilOperator as typeof takeUntilOperator & TakeUntilBrand & Function;
135+
export const combineLatest =
136+
combineLatestOperator as typeof combineLatestOperator & CombineLatestBrand & Function;

src/demo-app/table/table-demo.html

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,62 @@ <h3>MatTable Example</h3>
170170
[pageSizeOptions]="[5, 10, 25, 100]">
171171
</mat-paginator>
172172
</div>
173+
174+
175+
<h3>MatTable With MatTableDataSource Example</h3>
176+
177+
<mat-form-field>
178+
<input matInput [formControl]="filter">
179+
</mat-form-field>
180+
181+
<div class="demo-table-container demo-mat-table-example mat-elevation-z4">
182+
183+
<table-header-demo (shiftColumns)="displayedColumns.push(displayedColumns.shift())"
184+
(toggleColorColumn)="toggleColorColumn()">
185+
</table-header-demo>
186+
187+
<mat-table [dataSource]="matTableDataSource" [trackBy]="userTrackBy" matSort
188+
#sortForDataSource="matSort">
189+
190+
<!-- Column Definition: ID -->
191+
<ng-container cdkColumnDef="userId">
192+
<mat-header-cell *matHeaderCellDef mat-sort-header> ID </mat-header-cell>
193+
<mat-cell *matCellDef="let row"> {{row.id}} </mat-cell>
194+
</ng-container>
195+
196+
<!-- Column Definition: Progress -->
197+
<ng-container matColumnDef="progress">
198+
<mat-header-cell *matHeaderCellDef mat-sort-header> Progress </mat-header-cell>
199+
<mat-cell *matCellDef="let row">
200+
<div class="demo-progress-stat">{{row.progress}}%</div>
201+
<div class="demo-progress-indicator-container">
202+
<div class="demo-progress-indicator"
203+
[style.background]="row.progress > 50 ? 'green' : 'red'"
204+
[style.opacity]="getOpacity(row.progress)"
205+
[style.width.%]="row.progress"></div>
206+
</div>
207+
</mat-cell>
208+
</ng-container>
209+
210+
<!-- Column Definition: Name -->
211+
<ng-container matColumnDef="userName">
212+
<mat-header-cell *matHeaderCellDef mat-sort-header> Name </mat-header-cell>
213+
<mat-cell *matCellDef="let row"> {{row.name}} </mat-cell>
214+
</ng-container>
215+
216+
<!-- Column Definition: Color -->
217+
<ng-container matColumnDef="color">
218+
<mat-header-cell *matHeaderCellDef mat-sort-header>Color</mat-header-cell>
219+
<mat-cell *matCellDef="let row" [style.color]="row.color"> {{row.color}} </mat-cell>
220+
</ng-container>
221+
222+
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
223+
<mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
224+
225+
</mat-table>
226+
227+
<mat-paginator #paginatorForDataSource
228+
[length]="_peopleDatabase.data.length"
229+
[pageSizeOptions]="[10, 25, 100]">
230+
</mat-paginator>
231+
</div>

src/demo-app/table/table-demo.ts

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import {Component, ViewChild} from '@angular/core';
22
import {PeopleDatabase, UserData} from './people-database';
33
import {PersonDataSource} from './person-data-source';
4-
import {MatPaginator, MatSort} from '@angular/material';
4+
import {MatPaginator, MatSort, MatTableDataSource} from '@angular/material';
5+
import {FormControl} from '@angular/forms';
56

67
export type UserProperties = 'userId' | 'userName' | 'progress' | 'color' | undefined;
78

@@ -17,19 +18,43 @@ const properties = ['id', 'name', 'progress', 'color'];
1718
})
1819
export class TableDemo {
1920
dataSource: PersonDataSource | null;
21+
matTableDataSource = new MatTableDataSource<UserData>();
2022
displayedColumns: UserProperties[] = [];
2123
trackByStrategy: TrackByStrategy = 'reference';
2224
changeReferences = false;
2325
highlights = new Set<string>();
2426

27+
filter = new FormControl();
28+
2529
dynamicColumnDefs: any[] = [];
2630
dynamicColumnIds: string[] = [];
2731

28-
@ViewChild(MatPaginator) _paginator: MatPaginator;
29-
32+
@ViewChild(MatPaginator) paginator: MatPaginator;
3033
@ViewChild(MatSort) sort: MatSort;
3134

32-
constructor(public _peopleDatabase: PeopleDatabase) { }
35+
@ViewChild('paginatorForDataSource') paginatorForDataSource: MatPaginator;
36+
@ViewChild('sortForDataSource') sortForDataSource: MatSort;
37+
38+
constructor(public _peopleDatabase: PeopleDatabase) {
39+
this.matTableDataSource.sortingDataAccessor = (data: UserData, property: string) => {
40+
switch (property) {
41+
case 'userId': return +data.id;
42+
case 'userName': return data.name;
43+
case 'progress': return +data.progress;
44+
case 'color': return data.color;
45+
default: return '';
46+
}
47+
};
48+
this.matTableDataSource.filterTermAccessor = (data: UserData) => data.name;
49+
this.filter.valueChanges.subscribe(filter => this.matTableDataSource!.filter = filter);
50+
}
51+
52+
ngAfterViewInit() {
53+
// Needs to be set up after the view is initialized since the data source will look at the sort
54+
// and paginator's initial values to know what data should be rendered.
55+
this.matTableDataSource!.paginator = this.paginatorForDataSource;
56+
this.matTableDataSource!.sort = this.sortForDataSource;
57+
}
3358

3459
ngOnInit() {
3560
this.connect();
@@ -54,8 +79,9 @@ export class TableDemo {
5479
connect() {
5580
this.displayedColumns = ['userId', 'userName', 'progress', 'color'];
5681
this.dataSource = new PersonDataSource(this._peopleDatabase,
57-
this._paginator, this.sort);
82+
this.paginator, this.sort);
5883
this._peopleDatabase.initialize();
84+
this.matTableDataSource!.data = this._peopleDatabase.data.slice();
5985
}
6086

6187
disconnect() {

src/lib/sort/sort-header.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@
1616
</div>
1717

1818
<span class="cdk-visually-hidden" *ngIf="_isSorted()">
19-
{{_intl.sortDescriptionLabel(id, _sort.direction)}}
19+
&nbsp;{{_intl.sortDescriptionLabel(id, _sort.direction)}}
2020
</span>

src/lib/sort/sort.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export interface Sort {
2929
/** Container for MatSortables to manage the sort state and provide default sort parameters. */
3030
@Directive({
3131
selector: '[matSort]',
32+
exportAs: 'matSort'
3233
})
3334
export class MatSort {
3435
/** Collection of all registered sortables that this directive manages. */

src/lib/table/public-api.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ export * from './table-module';
1010
export * from './cell';
1111
export * from './table';
1212
export * from './row';
13-
13+
export * from './table-data-source';

0 commit comments

Comments
 (0)