Skip to content

Commit e55ec78

Browse files
andrewseguinkara
authored andcommitted
feat(data-table): allow dynamic data source (#5093)
1 parent b7e9e96 commit e55ec78

File tree

6 files changed

+192
-53
lines changed

6 files changed

+192
-53
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
<div class="demo-data-source-actions">
2+
<button md-raised-button (click)="connect()">Connect New Data Source</button>
3+
<button md-raised-button (click)="disconnect()" [disabled]="!dataSource">Disconnect Data Source</button>
4+
</div>
5+
16
<div class="demo-table-container mat-elevation-z4">
27

38
<table-header-demo (shiftColumns)="propertiesToDisplay.push(propertiesToDisplay.shift())"

src/demo-app/data-table/data-table-demo.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@
1212
}
1313
}
1414

15+
.demo-data-source-actions {
16+
margin: 16px 0;
17+
}
18+
1519
/*
1620
* Styles to make the demo's cdk-table match the material design spec
1721
* https://material.io/guidelines/components/data-tables.html
@@ -87,3 +91,4 @@
8791
font-family: cursive;
8892
}
8993
}
94+

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

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,21 @@ export type UserProperties = 'userId' | 'userName' | 'progress' | 'color';
1212
})
1313
export class DataTableDemo {
1414
dataSource: PersonDataSource;
15-
propertiesToDisplay: UserProperties[] = ['userId', 'userName', 'progress', 'color'];
15+
propertiesToDisplay: UserProperties[] = [];
1616

17-
constructor(private _peopleDatabase: PeopleDatabase) { }
17+
constructor(private _peopleDatabase: PeopleDatabase) {
18+
this.connect();
19+
}
1820

19-
ngOnInit() {
21+
connect() {
22+
this.propertiesToDisplay = ['userId', 'userName', 'progress', 'color'];
2023
this.dataSource = new PersonDataSource(this._peopleDatabase);
24+
this._peopleDatabase.initialize();
25+
}
26+
27+
disconnect() {
28+
this.dataSource = null;
29+
this.propertiesToDisplay = [];
2130
}
2231

2332
getOpacity(progress: number) {

src/demo-app/data-table/people-database.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ export class PeopleDatabase {
1616
data: UserData[] = [];
1717

1818
constructor() {
19+
this.initialize();
20+
}
21+
22+
initialize() {
23+
LATEST_ID = 0;
24+
this.data = [];
1925
for (let i = 0; i < 100; i++) { this.addPerson(); }
2026
}
2127

src/lib/core/data-table/data-table.spec.ts

Lines changed: 63 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ describe('CdkTable', () => {
2121

2222
TestBed.configureTestingModule({
2323
imports: [CdkDataTableModule],
24-
declarations: [SimpleCdkTableApp, CustomRoleCdkTableApp],
24+
declarations: [SimpleCdkTableApp, DynamicDataSourceCdkTableApp, CustomRoleCdkTableApp],
2525
}).compileComponents();
2626

2727
fixture = TestBed.createComponent(SimpleCdkTableApp);
@@ -164,6 +164,40 @@ describe('CdkTable', () => {
164164
]);
165165
});
166166

167+
it('should match the right table content with dynamic data source', () => {
168+
fixture = TestBed.createComponent(DynamicDataSourceCdkTableApp);
169+
component = fixture.componentInstance;
170+
tableElement = fixture.nativeElement.querySelector('cdk-table');
171+
172+
fixture.detectChanges(); // Let the table render the rows
173+
fixture.detectChanges(); // Let the rows render their cells
174+
175+
// Expect that the component has no data source and the table element reflects empty data.
176+
expect(component.dataSource).toBe(undefined);
177+
expect(tableElement).toMatchTableContent([
178+
['Column A']
179+
]);
180+
181+
// Add a data source that has initialized data. Expect that the table shows this data.
182+
component.dataSource = new FakeDataSource();
183+
fixture.detectChanges();
184+
185+
let data = component.dataSource.data;
186+
expect(tableElement).toMatchTableContent([
187+
['Column A'],
188+
[data[0].a],
189+
[data[1].a],
190+
[data[2].a],
191+
]);
192+
193+
// Remove the data source and check to make sure the table is empty again.
194+
component.dataSource = null;
195+
fixture.detectChanges();
196+
expect(tableElement).toMatchTableContent([
197+
['Column A']
198+
]);
199+
});
200+
167201
it('should be able to dynamically change the columns for header and rows', () => {
168202
expect(dataSource.data.length).toBe(3);
169203

@@ -262,6 +296,26 @@ class SimpleCdkTableApp {
262296
@ViewChild(CdkTable) table: CdkTable<TestData>;
263297
}
264298

299+
@Component({
300+
template: `
301+
<cdk-table [dataSource]="dataSource">
302+
<ng-container cdkColumnDef="column_a">
303+
<cdk-header-cell *cdkHeaderCellDef> Column A</cdk-header-cell>
304+
<cdk-cell *cdkCellDef="let row"> {{row.a}}</cdk-cell>
305+
</ng-container>
306+
307+
<cdk-header-row *cdkHeaderRowDef="columnsToRender"></cdk-header-row>
308+
<cdk-row *cdkRowDef="let row; columns: columnsToRender"></cdk-row>
309+
</cdk-table>
310+
`
311+
})
312+
class DynamicDataSourceCdkTableApp {
313+
dataSource: FakeDataSource;
314+
columnsToRender = ['column_a'];
315+
316+
@ViewChild(CdkTable) table: CdkTable<TestData>;
317+
}
318+
265319
@Component({
266320
template: `
267321
<cdk-table [dataSource]="dataSource" role="treegrid">
@@ -317,13 +371,19 @@ const tableCustomMatchers: jasmine.CustomMatcherFactories = {
317371
// Check header cells
318372
const expectedHeaderContent = expectedTableContent.shift();
319373
getHeaderCells(tableElement).forEach((cell, index) => {
320-
return checkCellContent(cell, expectedHeaderContent[index]);
374+
const expected = expectedHeaderContent ?
375+
expectedHeaderContent[index] :
376+
null;
377+
checkCellContent(cell, expected);
321378
});
322379

323380
// Check data row cells
324381
getRows(tableElement).forEach((row, rowIndex) => {
325382
getCells(row).forEach((cell, cellIndex) => {
326-
checkCellContent(cell, expectedTableContent[rowIndex][cellIndex]);
383+
const expected = expectedHeaderContent ?
384+
expectedTableContent[rowIndex][cellIndex] :
385+
null;
386+
checkCellContent(cell, expected);
327387
});
328388
});
329389

0 commit comments

Comments
 (0)