Skip to content

Commit 8b25d5b

Browse files
committed
feat(table): add MdTableDataSource
1 parent 1b6b270 commit 8b25d5b

File tree

8 files changed

+563
-149
lines changed

8 files changed

+563
-149
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: 10 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -19,124 +19,29 @@
1919
</div>
2020
</div>
2121

22-
<md-card class="demo-table-card">
23-
<h3>
24-
CdkTable With Dynamic Column Def
25-
<div>
26-
<button md-raised-button
27-
(click)="addDynamicColumnDef()"
28-
[disabled]="dynamicColumnIds.length >= 4">
29-
Add Column Def
30-
</button>
31-
<button md-raised-button
32-
(click)="removeDynamicColumnDef()"
33-
[disabled]="dynamicColumnIds.length == 0">
34-
Remove Column Def
35-
</button>
36-
</div>
37-
</h3>
38-
39-
<cdk-table [dataSource]="dataSource">
40-
<ng-container [cdkColumnDef]="column.id" *ngFor="let column of dynamicColumnDefs">
41-
<cdk-header-cell *cdkHeaderCellDef> {{column.headerText}} </cdk-header-cell>
42-
<cdk-cell *cdkCellDef="let row"> {{row[column.property]}} </cdk-cell>
43-
</ng-container>
44-
45-
<cdk-header-row *cdkHeaderRowDef="dynamicColumnIds"></cdk-header-row>
46-
<cdk-row *cdkRowDef="let row; columns: dynamicColumnIds;"></cdk-row>
47-
</cdk-table>
48-
</md-card>
49-
50-
<md-card class="demo-table-card">
51-
<h3>CdkTable Example</h3>
52-
53-
<div class="demo-highlighter">
54-
Highlight:
55-
<md-checkbox (change)="toggleHighlight('first', $event.checked)">First Row</md-checkbox>
56-
<md-checkbox (change)="toggleHighlight('last', $event.checked)">Last Row</md-checkbox>
57-
<md-checkbox (change)="toggleHighlight('even', $event.checked)">Even Rows</md-checkbox>
58-
<md-checkbox (change)="toggleHighlight('odd', $event.checked)">Odd Rows</md-checkbox>
59-
</div>
60-
61-
<cdk-table #table mdSort
62-
[dataSource]="dataSource"
63-
[trackBy]="userTrackBy">
64-
65-
<!-- Column Definition: ID -->
66-
<ng-container cdkColumnDef="userId">
67-
<cdk-header-cell *cdkHeaderCellDef
68-
md-sort-header arrowPosition="before">
69-
ID
70-
</cdk-header-cell>
71-
<cdk-cell *cdkCellDef="let row"> {{row.id}} </cdk-cell>
72-
</ng-container>
73-
74-
<!-- Column Definition: Progress -->
75-
<ng-container cdkColumnDef="progress">
76-
<cdk-header-cell *cdkHeaderCellDef
77-
md-sort-header start="desc">
78-
Progress
79-
</cdk-header-cell>
80-
<cdk-cell *cdkCellDef="let row">
81-
<div class="demo-progress-stat">{{row.progress}}%</div>
82-
<div class="demo-progress-indicator-container">
83-
<div class="demo-progress-indicator"
84-
[style.background]="row.progress > 50 ? 'green' : 'red'"
85-
[style.opacity]="getOpacity(row.progress)"
86-
[style.width.%]="row.progress"></div>
87-
</div>
88-
</cdk-cell>
89-
</ng-container>
90-
91-
<!-- Column Definition: Name -->
92-
<ng-container cdkColumnDef="userName">
93-
<cdk-header-cell *cdkHeaderCellDef md-sort-header>
94-
Name
95-
</cdk-header-cell>
96-
<cdk-cell *cdkCellDef="let row"> {{row.name}} </cdk-cell>
97-
</ng-container>
98-
99-
<!-- Column Definition: Color -->
100-
<ng-container cdkColumnDef="color">
101-
<cdk-header-cell *cdkHeaderCellDef
102-
md-sort-header disableClear>
103-
Color
104-
</cdk-header-cell>
105-
<cdk-cell *cdkCellDef="let row" [style.color]="row.color"> {{row.color}} </cdk-cell>
106-
</ng-container>
107-
108-
<cdk-header-row *cdkHeaderRowDef="displayedColumns"></cdk-header-row>
109-
<cdk-row *cdkRowDef="let row; columns: displayedColumns;
110-
let first = first; let last = last; let even = even; let odd = odd"
111-
[ngClass]="{
112-
'demo-row-highlight-first': highlights.has('first') && first,
113-
'demo-row-highlight-last': highlights.has('last') && last,
114-
'demo-row-highlight-even': highlights.has('even') && even,
115-
'demo-row-highlight-odd': highlights.has('odd') && odd
116-
}">
117-
</cdk-row>
118-
</cdk-table>
119-
</md-card>
120-
12122
<h3>MdTable Example</h3>
12223

24+
<md-form-field>
25+
<input mdInput [formControl]="filter">
26+
</md-form-field>
27+
12328
<div class="demo-table-container demo-mat-table-example mat-elevation-z4">
12429

12530
<table-header-demo (shiftColumns)="displayedColumns.push(displayedColumns.shift())"
12631
(toggleColorColumn)="toggleColorColumn()">
12732
</table-header-demo>
12833

129-
<md-table [dataSource]="dataSource" [trackBy]="userTrackBy">
34+
<md-table [dataSource]="dataSource" [trackBy]="userTrackBy" mdSort>
13035

13136
<!-- Column Definition: ID -->
13237
<ng-container cdkColumnDef="userId">
133-
<md-header-cell *mdHeaderCellDef> ID </md-header-cell>
38+
<md-header-cell *mdHeaderCellDef md-sort-header> ID </md-header-cell>
13439
<md-cell *mdCellDef="let row"> {{row.id}} </md-cell>
13540
</ng-container>
13641

13742
<!-- Column Definition: Progress -->
13843
<ng-container mdColumnDef="progress">
139-
<md-header-cell *mdHeaderCellDef> Progress </md-header-cell>
44+
<md-header-cell *mdHeaderCellDef md-sort-header> Progress </md-header-cell>
14045
<md-cell *mdCellDef="let row">
14146
<div class="demo-progress-stat">{{row.progress}}%</div>
14247
<div class="demo-progress-indicator-container">
@@ -150,13 +55,13 @@ <h3>MdTable Example</h3>
15055

15156
<!-- Column Definition: Name -->
15257
<ng-container mdColumnDef="userName">
153-
<md-header-cell *mdHeaderCellDef> Name </md-header-cell>
58+
<md-header-cell *mdHeaderCellDef md-sort-header> Name </md-header-cell>
15459
<md-cell *mdCellDef="let row"> {{row.name}} </md-cell>
15560
</ng-container>
15661

15762
<!-- Column Definition: Color -->
15863
<ng-container mdColumnDef="color">
159-
<md-header-cell *mdHeaderCellDef>Color</md-header-cell>
64+
<md-header-cell *mdHeaderCellDef md-sort-header>Color</md-header-cell>
16065
<md-cell *mdCellDef="let row" [style.color]="row.color"> {{row.color}} </md-cell>
16166
</ng-container>
16267

@@ -167,6 +72,6 @@ <h3>MdTable Example</h3>
16772

16873
<md-paginator #paginator
16974
[length]="_peopleDatabase.data.length"
170-
[pageSizeOptions]="[5, 10, 25, 100]">
75+
[pageSizeOptions]="[10, 25, 100]">
17176
</md-paginator>
17277
</div>

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

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import {Component, ViewChild} from '@angular/core';
22
import {PeopleDatabase, UserData} from './people-database';
3-
import {PersonDataSource} from './person-data-source';
4-
import {MdPaginator, MdSort} from '@angular/material';
3+
import {MdPaginator, MdSort, MdTableDataSource} from '@angular/material';
4+
import {FormControl} from '@angular/forms';
5+
import 'rxjs/add/operator/debounceTime';
6+
57

68
export type UserProperties = 'userId' | 'userName' | 'progress' | 'color' | undefined;
79

@@ -16,23 +18,41 @@ const properties = ['id', 'name', 'progress', 'color'];
1618
styleUrls: ['table-demo.css'],
1719
})
1820
export class TableDemo {
19-
dataSource: PersonDataSource | null;
20-
displayedColumns: UserProperties[] = [];
21+
dataSource: MdTableDataSource<UserData>|null;
22+
displayedColumns: UserProperties[] = ['userId', 'userName', 'progress', 'color'];
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(MdPaginator) _paginator: MdPaginator;
32+
@ViewChild(MdPaginator) paginator: MdPaginator;
2933

3034
@ViewChild(MdSort) sort: MdSort;
3135

32-
constructor(public _peopleDatabase: PeopleDatabase) { }
36+
constructor(public _peopleDatabase: PeopleDatabase) {
37+
this.dataSource = new MdTableDataSource(this._peopleDatabase.data);
38+
this.dataSource.sortingDataAccessor = (data: UserData, property: string) => {
39+
switch (property) {
40+
case 'userId': return +data.id;
41+
case 'userName': return data.name;
42+
case 'progress': return +data.progress;
43+
case 'color': return data.color;
44+
default: return '';
45+
}
46+
};
47+
this.dataSource.filterTermAccessor = (data: UserData) => data.name;
48+
this.filter.valueChanges.subscribe(filter => this.dataSource!.filter = filter);
49+
}
3350

34-
ngOnInit() {
35-
this.connect();
51+
ngAfterViewInit() {
52+
// Needs to be set up after the view is initialized since the data source will look at the sort
53+
// and paginator's initial values to know what data should be rendered.
54+
this.dataSource!.sort = this.sort;
55+
this.dataSource!.paginator = this.paginator;
3656
}
3757

3858
addDynamicColumnDef() {
@@ -53,13 +73,11 @@ export class TableDemo {
5373

5474
connect() {
5575
this.displayedColumns = ['userId', 'userName', 'progress', 'color'];
56-
this.dataSource = new PersonDataSource(this._peopleDatabase,
57-
this._paginator, this.sort);
5876
this._peopleDatabase.initialize();
77+
this.dataSource!.data = this._peopleDatabase.data;
5978
}
6079

6180
disconnect() {
62-
this.dataSource = null;
6381
this.displayedColumns = [];
6482
}
6583

src/lib/core/rxjs/rx-operators.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export {
2020
DebounceTimeBrand,
2121
AuditTimeBrand,
2222
TakeUntilBrand,
23+
CombineLatestBrand,
2324
finallyOperatorType,
2425
catchOperatorType,
2526
doOperatorType,
@@ -32,6 +33,7 @@ export {
3233
debounceTimeOperatorType,
3334
auditTimeOperatorType,
3435
takeUntilOperatorType,
36+
combineLatestOperatorType,
3537
finallyOperator,
3638
catchOperator,
3739
doOperator,
@@ -44,4 +46,5 @@ export {
4446
debounceTime,
4547
auditTime,
4648
takeUntil,
49+
combineLatest,
4750
} from '@angular/cdk/rxjs';

src/lib/table/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {MdCommonModule} from '../core';
1717
export * from './cell';
1818
export * from './table';
1919
export * from './row';
20+
export * from './table-data-source';
2021

2122
@NgModule({
2223
imports: [CdkTableModule, CommonModule, MdCommonModule],

0 commit comments

Comments
 (0)