feat(table): add md-table (cdk-table with style) (#5340)

* add files

* checkin

* add simple data source

* checkin

* checkin

* just md table

* minor

* add test

* add files

* add explicit type

* fill out test

* change import

* take out simple stuff

* add mat class to columns

* add to compat

* fix import

* Add test for real

* without fdescribe

* change to a const template

* rebase

* lint
This commit is contained in:
Andrew Seguin
2017-06-29 10:23:56 -07:00
committed by tinayuangao
parent f73cc977ec
commit cadc18a781
20 changed files with 484 additions and 121 deletions
+83 -42
View File
@@ -27,61 +27,57 @@
</div>
</div>
<div class="demo-table-container mat-elevation-z4">
<h3>CdkTable Example</h3>
<table-header-demo (shiftColumns)="propertiesToDisplay.push(propertiesToDisplay.shift())"
(toggleColorColumn)="toggleColorColumn()">
</table-header-demo>
<cdk-table #table mdSort
<cdk-table #table mdSort
[dataSource]="dataSource"
[trackBy]="userTrackBy">
<!-- Column Definition: ID -->
<ng-container cdkColumnDef="userId">
<cdk-header-cell *cdkHeaderCellDef
md-sort-header arrowPosition="before">
<!-- Column Definition: ID -->
<ng-container cdkColumnDef="userId">
<cdk-header-cell *cdkHeaderCellDef
md-sort-header arrowPosition="before">
ID
</cdk-header-cell>
<cdk-cell *cdkCellDef="let row"> {{row.id}} </cdk-cell>
</ng-container>
<cdk-cell *cdkCellDef="let row"> {{row.id}} </cdk-cell>
</ng-container>
<!-- Column Definition: Progress -->
<ng-container cdkColumnDef="progress">
<cdk-header-cell *cdkHeaderCellDef
<!-- Column Definition: Progress -->
<ng-container cdkColumnDef="progress">
<cdk-header-cell *cdkHeaderCellDef
md-sort-header start="desc">
Progress
</cdk-header-cell>
<cdk-cell *cdkCellDef="let row">
<div class="demo-progress-stat">{{row.progress}}%</div>
<div class="demo-progress-indicator-container">
<div class="demo-progress-indicator"
[style.background]="row.progress > 50 ? 'green' : 'red'"
[style.opacity]="getOpacity(row.progress)"
[style.width.%]="row.progress"></div>
</div>
</cdk-cell>
</ng-container>
<cdk-cell *cdkCellDef="let row">
<div class="demo-progress-stat">{{row.progress}}%</div>
<div class="demo-progress-indicator-container">
<div class="demo-progress-indicator"
[style.background]="row.progress > 50 ? 'green' : 'red'"
[style.opacity]="getOpacity(row.progress)"
[style.width.%]="row.progress"></div>
</div>
</cdk-cell>
</ng-container>
<!-- Column Definition: Name -->
<ng-container cdkColumnDef="userName">
<cdk-header-cell *cdkHeaderCellDef md-sort-header>
<!-- Column Definition: Name -->
<ng-container cdkColumnDef="userName">
<cdk-header-cell *cdkHeaderCellDef md-sort-header>
Name
</cdk-header-cell>
<cdk-cell *cdkCellDef="let row"> {{row.name}} </cdk-cell>
</ng-container>
<cdk-cell *cdkCellDef="let row"> {{row.name}} </cdk-cell>
</ng-container>
<!-- Column Definition: Color -->
<ng-container cdkColumnDef="color">
<cdk-header-cell *cdkHeaderCellDef
<!-- Column Definition: Color -->
<ng-container cdkColumnDef="color">
<cdk-header-cell *cdkHeaderCellDef
md-sort-header disableClear>
Color
</cdk-header-cell>
<cdk-cell *cdkCellDef="let row" [style.color]="row.color"> {{row.color}} </cdk-cell>
</ng-container>
<cdk-cell *cdkCellDef="let row" [style.color]="row.color"> {{row.color}} </cdk-cell>
</ng-container>
<cdk-header-row *cdkHeaderRowDef="propertiesToDisplay"></cdk-header-row>
<cdk-row *cdkRowDef="let row; columns: propertiesToDisplay;
<cdk-header-row *cdkHeaderRowDef="propertiesToDisplay"></cdk-header-row>
<cdk-row *cdkRowDef="let row; columns: propertiesToDisplay;
let first = first; let last = last; let even = even; let odd = odd"
[ngClass]="{
'demo-row-highlight-first': highlights.has('first') && first,
@@ -90,12 +86,57 @@
'demo-row-highlight-odd': highlights.has('odd') && odd
}">
</cdk-row>
</cdk-table>
</cdk-table>
<h3>MdTable Example</h3>
<div class="demo-table-container demo-mat-table-example mat-elevation-z4">
<table-header-demo (shiftColumns)="propertiesToDisplay.push(propertiesToDisplay.shift())"
(toggleColorColumn)="toggleColorColumn()">
</table-header-demo>
<md-table [dataSource]="dataSource" [trackBy]="userTrackBy">
<!-- Column Definition: ID -->
<ng-container cdkColumnDef="userId">
<md-header-cell *cdkHeaderCellDef> ID </md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.id}} </md-cell>
</ng-container>
<!-- Column Definition: Progress -->
<ng-container cdkColumnDef="progress">
<md-header-cell *cdkHeaderCellDef> Progress </md-header-cell>
<md-cell *cdkCellDef="let row">
<div class="demo-progress-stat">{{row.progress}}%</div>
<div class="demo-progress-indicator-container">
<div class="demo-progress-indicator"
[style.background]="row.progress > 50 ? 'green' : 'red'"
[style.opacity]="getOpacity(row.progress)"
[style.width.%]="row.progress"></div>
</div>
</md-cell>
</ng-container>
<!-- Column Definition: Name -->
<ng-container cdkColumnDef="userName">
<md-header-cell *cdkHeaderCellDef> Name </md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.name}} </md-cell>
</ng-container>
<!-- Column Definition: Color -->
<ng-container cdkColumnDef="color">
<md-header-cell *cdkHeaderCellDef>Color</md-header-cell>
<md-cell *cdkCellDef="let row" [style.color]="row.color"> {{row.color}} </md-cell>
</ng-container>
<md-header-row *cdkHeaderRowDef="propertiesToDisplay"></md-header-row>
<md-row *cdkRowDef="let row; columns: propertiesToDisplay"></md-row>
</md-table>
<md-paginator #paginator
[length]="_peopleDatabase.data.length"
[pageIndex]="0"
[pageSize]="10"
[pageSizeOptions]="[5, 10, 25, 100]">
</md-paginator>
</div>
</div>
+38 -59
View File
@@ -1,17 +1,3 @@
/* Structure */
.demo-table-container {
display: flex;
flex-direction: column;
max-height: 800px;
background: white;
// Table fills in the remaining area with a scroll
.cdk-table {
flex: 1 1 auto;
overflow: auto;
}
}
.demo-data-source-actions {
& > div {
margin: 16px 0;
@@ -36,45 +22,45 @@
.demo-row-highlight-even { background: #ff0099; }
.demo-row-highlight-odd { background: #83f52c; }
/*
* Styles to make the demo's cdk-table match the material design spec
* https://material.io/guidelines/components/data-tables.html
*/
/** Styles so that the CDK Table columns have width and font size. */
.cdk-table {
display: block;
}
.cdk-row, .cdk-header-row {
display: flex;
border-bottom: 1px solid #ccc;
align-items: center;
height: 48px;
padding: 0 8px;
}
.cdk-cell, .cdk-header-cell {
width: 150px;
padding: 10px;
position: relative;
flex: 1;
}
.cdk-header-cell {
font-size: 12px;
font-weight: bold;
color: rgba(0, 0, 0, 0.54);
&.mat-sort-header-sorted {
color: black;
.cdk-row, .cdk-header-row {
display: flex;
}
.cdk-cell, .cdk-header-cell {
flex: 1;
}
.cdk-header-cell {
font-weight: bold;
&.mat-sort-header-sorted {
color: black;
}
}
}
.cdk-cell {
font-size: 13px;
color: rgba(0, 0, 0, 0.87);
.demo-mat-table-example {
table-header-demo {
background: white;
}
}
/* Column and cell styles */
/* Structure so that the table is contained on a card */
.demo-table-container {
max-height: 800px;
display: flex;
flex-direction: column;
md-table {
overflow: auto;
}
}
/* Column max widths */
.cdk-column-userId {
max-width: 32px;
text-align: right;
@@ -82,13 +68,17 @@
}
.cdk-column-userName {
max-width: 80px;
max-width: 120px;
}
.cdk-column-color {
max-width: 160px;
}
/* Progress bar styling */
.cdk-column-progress {
&.cdk-cell {
&.cdk-cell, &.mat-cell {
display: flex;
position: relative;
.demo-progress-stat {
width: 32px;
@@ -96,7 +86,6 @@
}
.demo-progress-indicator-container {
position: relative;
flex-grow: 1;
display: flex;
align-items: center;
@@ -107,13 +96,3 @@
}
}
}
.cdk-column-color {
max-width: 160px;
&.cdk-cell {
font-weight: bold;
font-size: 16px;
font-family: cursive;
}
}
@@ -3,7 +3,7 @@
align-items: center;
justify-content: space-between;
min-height: 64px;
padding: 0 16px;
padding: 0 24px;
}
.title {
+2
View File
@@ -52,6 +52,7 @@ import {
MdCheckboxModule,
MdChipsModule,
MdCoreModule,
MdTableModule,
MdDatepickerModule,
MdDialogModule,
MdExpansionModule,
@@ -91,6 +92,7 @@ import {TableHeaderDemo} from './data-table/table-header-demo';
MdCardModule,
MdCheckboxModule,
MdChipsModule,
MdTableModule,
MdDatepickerModule,
MdDialogModule,
MdExpansionModule,
@@ -50,6 +50,7 @@ export const MAT_ELEMENTS_SELECTOR = `
mat-card-subtitle,
mat-card-title,
mat-card-title-group,
mat-cell,
mat-checkbox,
mat-chip,
mat-dialog-actions,
@@ -61,6 +62,7 @@ export const MAT_ELEMENTS_SELECTOR = `
mat-grid-tile,
mat-grid-tile-footer,
mat-grid-tile-header,
mat-header-cell,
mat-hint,
mat-icon,
mat-list,
@@ -73,12 +75,14 @@ export const MAT_ELEMENTS_SELECTOR = `
mat-pseudo-checkbox,
mat-radio-button,
mat-radio-group,
mat-row,
mat-select,
mat-sidenav,
mat-sidenav-container,
mat-slider,
mat-spinner,
mat-tab,
mat-table,
mat-tab-group,
mat-toolbar`;
@@ -112,6 +116,7 @@ export const MD_ELEMENTS_SELECTOR = `
md-card-subtitle,
md-card-title,
md-card-title-group,
md-cell,
md-checkbox,
md-chip,
md-dialog-actions,
@@ -123,6 +128,7 @@ export const MD_ELEMENTS_SELECTOR = `
md-grid-tile,
md-grid-tile-footer,
md-grid-tile-header,
md-header-cell,
md-hint,
md-icon,
md-list,
@@ -135,12 +141,14 @@ export const MD_ELEMENTS_SELECTOR = `
md-pseudo-checkbox,
md-radio-button,
md-radio-group,
md-row,
md-select,
md-sidenav,
md-sidenav-container,
md-slider,
md-spinner,
md-tab,
md-table,
md-tab-group,
md-toolbar`;
+11 -4
View File
@@ -65,16 +65,21 @@ export class HeaderRowPlaceholder {
constructor(public viewContainer: ViewContainerRef) { }
}
/**
* The table template that can be used by the md-table. Should not be used outside of the
* material library.
*/
export const CDK_TABLE_TEMPLATE = `
<ng-container headerRowPlaceholder></ng-container>
<ng-container rowPlaceholder></ng-container>`;
/**
* A data table that connects with a data source to retrieve data of type T and renders
* a header row and data rows. Updates the rows when new data is provided by the data source.
*/
@Component({
selector: 'cdk-table',
template: `
<ng-container headerRowPlaceholder></ng-container>
<ng-container rowPlaceholder></ng-container>
`,
template: CDK_TABLE_TEMPLATE,
host: {
'class': 'cdk-table',
},
@@ -347,6 +352,7 @@ export class CdkTable<T> implements CollectionViewer {
* as defined by its list of columns to display.
*/
private _getHeaderCellTemplatesForRow(headerDef: CdkHeaderRowDef): CdkHeaderCellDef[] {
if (!headerDef.columns) { return []; }
return headerDef.columns.map(columnId => {
const column = this._columnDefinitionsByName.get(columnId);
@@ -363,6 +369,7 @@ export class CdkTable<T> implements CollectionViewer {
* as defined by its list of columns to display.
*/
private _getCellTemplatesForRow(rowDef: CdkRowDef): CdkCellDef[] {
if (!rowDef.columns) { return []; }
return rowDef.columns.map(columnId => {
const column = this._columnDefinitionsByName.get(columnId);
+18 -10
View File
@@ -15,18 +15,26 @@ import {CdkColumnDef, CdkHeaderCellDef, CdkHeaderCell, CdkCell, CdkCellDef} from
export * from './data-source';
export * from './data-table';
const EXPORTED_DECLARATIONS = [
CdkTable,
CdkRowDef,
CdkCellDef,
CdkCellOutlet,
CdkHeaderCellDef,
CdkColumnDef,
CdkCell,
CdkRow,
CdkHeaderCell,
CdkHeaderRow,
CdkHeaderRowDef,
RowPlaceholder,
HeaderRowPlaceholder,
];
@NgModule({
imports: [CommonModule],
exports: [
CdkTable, CdkRowDef, CdkCellDef, CdkCellOutlet, CdkHeaderCellDef,
CdkColumnDef, CdkCell, CdkRow,
CdkHeaderCell, CdkHeaderRow, CdkHeaderRowDef],
declarations: [
CdkTable, CdkRowDef, CdkCellDef, CdkCellOutlet, CdkHeaderCellDef,
CdkColumnDef, CdkCell, CdkRow,
CdkHeaderCell, CdkHeaderRow, CdkHeaderRowDef,
RowPlaceholder, HeaderRowPlaceholder,
]
exports: [EXPORTED_DECLARATIONS],
declarations: [EXPORTED_DECLARATIONS]
})
export class CdkDataTableModule { }
+9 -3
View File
@@ -19,6 +19,12 @@ import {
import {CdkCellDef} from './cell';
import {Subject} from 'rxjs/Subject';
/**
* The row template that can be used by the md-table. Should not be used outside of the
* material library.
*/
export const CDK_ROW_TEMPLATE = `<ng-container cdkCellOutlet></ng-container>`;
/**
* Base class for the CdkHeaderRowDef and CdkRowDef that handles checking their columns inputs
* for changes and notifying the table.
@@ -45,7 +51,7 @@ export abstract class BaseRowDef {
ngOnChanges(changes: SimpleChanges): void {
// Create a new columns differ if one does not yet exist. Initialize it based on initial value
// of the columns property.
if (!this._columnsDiffer) {
if (!this._columnsDiffer && changes['columns'].currentValue) {
this._columnsDiffer = this._differs.find(changes['columns'].currentValue).create();
}
}
@@ -142,7 +148,7 @@ export class CdkCellOutlet {
/** Header template container that contains the cell outlet. Adds the right class and role. */
@Component({
selector: 'cdk-header-row',
template: '<ng-container cdkCellOutlet></ng-container>',
template: CDK_ROW_TEMPLATE,
host: {
'class': 'cdk-header-row',
'role': 'row',
@@ -154,7 +160,7 @@ export class CdkHeaderRow { }
/** Data row template container that contains the cell outlet. Adds the right class and role. */
@Component({
selector: 'cdk-row',
template: '<ng-container cdkCellOutlet></ng-container>',
template: CDK_ROW_TEMPLATE,
host: {
'class': 'cdk-row',
'role': 'row',
+2
View File
@@ -6,6 +6,7 @@
@import '../../card/card-theme';
@import '../../checkbox/checkbox-theme';
@import '../../chips/chips-theme';
@import '../../table/table-theme';
@import '../../datepicker/datepicker-theme';
@import '../../dialog/dialog-theme';
@import '../../expansion/expansion-theme';
@@ -37,6 +38,7 @@
@include mat-card-theme($theme);
@include mat-checkbox-theme($theme);
@include mat-chips-theme($theme);
@include mat-table-theme($theme);
@include mat-datepicker-theme($theme);
@include mat-dialog-theme($theme);
@include mat-expansion-panel-theme($theme);
@@ -5,6 +5,7 @@
@import '../../card/card-theme';
@import '../../checkbox/checkbox-theme';
@import '../../chips/chips-theme';
@import '../../table/table-theme';
@import '../../datepicker/datepicker-theme';
@import '../../dialog/dialog-theme';
@import '../../grid-list/grid-list-theme';
@@ -37,6 +38,7 @@
@include mat-card-typography($config);
@include mat-checkbox-typography($config);
@include mat-chips-typography($config);
@include mat-table-typography($config);
@include mat-datepicker-typography($config);
@include mat-dialog-typography($config);
@include mat-grid-list-typography($config);
+4 -2
View File
@@ -10,9 +10,9 @@ import {NgModule} from '@angular/core';
import {
A11yModule,
BidiModule,
MdCommonModule,
MdRippleModule,
BidiModule,
ObserveContentModule,
OverlayModule,
PortalModule
@@ -46,6 +46,7 @@ import {StyleModule} from './core/style/index';
import {MdDatepickerModule} from './datepicker/index';
import {CdkDataTableModule} from './core/data-table/index';
import {MdExpansionModule} from './expansion/index';
import {MdTableModule} from './table/index';
import {MdSortModule} from './sort/index';
import {MdPaginatorModule} from './paginator/index';
@@ -57,6 +58,7 @@ const MATERIAL_MODULES = [
MdChipsModule,
MdCheckboxModule,
MdDatepickerModule,
MdTableModule,
MdDialogModule,
MdExpansionModule,
MdGridListModule,
@@ -86,7 +88,7 @@ const MATERIAL_MODULES = [
PlatformModule,
MdCommonModule,
ObserveContentModule,
CdkDataTableModule
CdkDataTableModule,
];
/** @deprecated */
+5
View File
@@ -5,6 +5,11 @@
@mixin mat-paginator-theme($theme) {
$foreground: map-get($theme, foreground);
$background: map-get($theme, background);
.mat-paginator {
background: mat-color($background, 'card');
}
.mat-paginator,
.mat-paginator-page-size .mat-select-trigger {
+1
View File
@@ -22,6 +22,7 @@ export * from './card/index';
export * from './chips/index';
export * from './checkbox/index';
export * from './core/data-table/index';
export * from './table/index';
export * from './datepicker/index';
export * from './dialog/index';
export * from './expansion/index';
+37
View File
@@ -0,0 +1,37 @@
@import '../core/theming/palette';
@import '../core/theming/theming';
@import '../core/typography/typography-utils';
@mixin mat-table-theme($theme) {
$background: map-get($theme, background);
$foreground: map-get($theme, foreground);
.mat-table {
background: mat-color($background, 'card');
}
.mat-row, .mat-header-row {
border-bottom-color: mat-color($foreground, divider);
}
.mat-header-cell {
color: mat-color($foreground, secondary-text);
}
.mat-cell {
color: mat-color($foreground, text);
}
}
@mixin mat-table-typography($config) {
$font-family: mat-font-family($config);
.mat-header-cell {
font-size: mat-font-size($config, caption);
font-weight: mat-font-weight($config, body-2);
}
.mat-cell {
font-size: mat-font-size($config, body-1);
}
}
+44
View File
@@ -0,0 +1,44 @@
/**
* @license
* Copyright Google Inc. 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, ElementRef, Renderer2} from '@angular/core';
import {CdkCell, CdkColumnDef, CdkHeaderCell} from '../core/data-table/cell';
/** Header cell template container that adds the right classes and role. */
@Directive({
selector: 'md-header-cell, mat-header-cell',
host: {
'class': 'mat-header-cell',
'role': 'columnheader',
},
})
export class MdHeaderCell extends CdkHeaderCell {
constructor(columnDef: CdkColumnDef,
elementRef: ElementRef,
renderer: Renderer2) {
super(columnDef, elementRef, renderer);
renderer.addClass(elementRef.nativeElement, `mat-column-${columnDef.name}`);
}
}
/** Cell template container that adds the right classes and role. */
@Directive({
selector: 'md-cell, mat-cell',
host: {
'class': 'mat-cell',
'role': 'gridcell',
},
})
export class MdCell extends CdkCell {
constructor(columnDef: CdkColumnDef,
elementRef: ElementRef,
renderer: Renderer2) {
super(columnDef, elementRef, renderer);
renderer.addClass(elementRef.nativeElement, `mat-column-${columnDef.name}`);
}
}
+26
View File
@@ -0,0 +1,26 @@
/**
* @license
* Copyright Google Inc. 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 {NgModule} from '@angular/core';
import {MdTable} from './table';
import {CdkDataTableModule} from '../core/data-table/index';
import {MdCell, MdHeaderCell} from './cell';
import {MdHeaderRow, MdRow} from './row';
import {CommonModule} from '@angular/common';
import {MdCommonModule} from '../core';
export * from './cell';
export * from './table';
export * from './row';
@NgModule({
imports: [CdkDataTableModule, CommonModule, MdCommonModule],
exports: [MdTable, MdHeaderCell, MdCell, MdHeaderRow, MdRow],
declarations: [MdTable, MdHeaderCell, MdCell, MdHeaderRow, MdRow],
})
export class MdTableModule {}
+34
View File
@@ -0,0 +1,34 @@
/**
* @license
* Copyright Google Inc. 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 {ChangeDetectionStrategy, Component} from '@angular/core';
import {CdkHeaderRow, CdkRow, CDK_ROW_TEMPLATE} from '../core/data-table/row';
/** Header template container that contains the cell outlet. Adds the right class and role. */
@Component({
selector: 'md-header-row, mat-header-row',
template: CDK_ROW_TEMPLATE,
host: {
'class': 'mat-header-row',
'role': 'row',
},
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MdHeaderRow extends CdkHeaderRow { }
/** Data row template container that contains the cell outlet. Adds the right class and role. */
@Component({
selector: 'md-row, mat-row',
template: CDK_ROW_TEMPLATE,
host: {
'class': 'mat-row',
'role': 'row',
},
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MdRow extends CdkRow { }
+19
View File
@@ -0,0 +1,19 @@
$mat-row-height: 48px;
$mat-row-horizontal-padding: 24px;
.mat-table {
display: block;
}
.mat-row, .mat-header-row {
display: flex;
border-bottom-width: 1px;
border-bottom-style: solid;
align-items: center;
height: $mat-row-height;
padding: 0 $mat-row-horizontal-padding;
}
.mat-cell, .mat-header-cell {
flex: 1;
}
+114
View File
@@ -0,0 +1,114 @@
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {Component, ViewChild} from '@angular/core';
import {CdkTable} from '../core/data-table/data-table';
import {DataSource} from '../core/data-table/data-source';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import {Observable} from 'rxjs/Observable';
import {CdkDataTableModule} from '../core/data-table/index';
import {MdTableModule} from './index';
describe('MdTable', () => {
let fixture: ComponentFixture<SimpleMdTableApp>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [MdTableModule, CdkDataTableModule],
declarations: [SimpleMdTableApp],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(SimpleMdTableApp);
fixture.detectChanges();
fixture.detectChanges();
});
it('should create a table with the right content', () => {
const tableElement = fixture.nativeElement.querySelector('.mat-table');
const headerRow = tableElement.querySelectorAll('.mat-header-cell');
expectTextContent(headerRow[0], 'Column A');
expectTextContent(headerRow[1], 'Column B');
expectTextContent(headerRow[2], 'Column C');
const rows = tableElement.querySelectorAll('.mat-row');
for (let i = 0; i < rows.length; i++) {
const cells = rows[i].querySelectorAll('.mat-cell');
expectTextContent(cells[0], `a_${i + 1}`);
expectTextContent(cells[1], `b_${i + 1}`);
expectTextContent(cells[2], `c_${i + 1}`);
}
});
});
function expectTextContent(el, text) {
if (el && el.textContent) {
expect(el.textContent.trim()).toBe(text);
} else {
fail(`Missing text content of ${text} in element ${el}`);
}
}
interface TestData {
a: string;
b: string;
c: string;
}
class FakeDataSource extends DataSource<TestData> {
_dataChange = new BehaviorSubject<TestData[]>([]);
set data(data: TestData[]) { this._dataChange.next(data); }
get data() { return this._dataChange.getValue(); }
constructor() {
super();
for (let i = 0; i < 3; i++) { this.addData(); }
}
connect(): Observable<TestData[]> {
return this._dataChange;
}
addData() {
const nextIndex = this.data.length + 1;
let copiedData = this.data.slice();
copiedData.push({
a: `a_${nextIndex}`,
b: `b_${nextIndex}`,
c: `c_${nextIndex}`
});
this.data = copiedData;
}
}
@Component({
template: `
<md-table [dataSource]="dataSource">
<ng-container cdkColumnDef="column_a">
<md-header-cell *cdkHeaderCellDef> Column A</md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.a}}</md-cell>
</ng-container>
<ng-container cdkColumnDef="column_b">
<md-header-cell *cdkHeaderCellDef> Column B</md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.b}}</md-cell>
</ng-container>
<ng-container cdkColumnDef="column_c">
<md-header-cell *cdkHeaderCellDef> Column C</md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.c}}</md-cell>
</ng-container>
<md-header-row *cdkHeaderRowDef="columnsToRender"></md-header-row>
<md-row *cdkRowDef="let row; columns: columnsToRender"></md-row>
</md-table>
`
})
class SimpleMdTableApp {
dataSource: FakeDataSource | null = new FakeDataSource();
columnsToRender = ['column_a', 'column_b', 'column_c'];
@ViewChild(CdkTable) table: CdkTable<TestData>;
}
+26
View File
@@ -0,0 +1,26 @@
/**
* @license
* Copyright Google Inc. 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 {ChangeDetectionStrategy, Component, ViewEncapsulation} from '@angular/core';
import {CDK_TABLE_TEMPLATE, CdkTable} from '../core/data-table/data-table';
/**
* Wrapper for the CdkTable with Material design styles.
*/
@Component({
moduleId: module.id,
selector: 'md-table, mat-table',
template: CDK_TABLE_TEMPLATE,
styleUrls: ['table.css'],
host: {
'class': 'mat-table',
},
encapsulation: ViewEncapsulation.None,
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class MdTable<T> extends CdkTable<T> { }