From 197d32df9611f16cdb53421c0878e3ee10f62222 Mon Sep 17 00:00:00 2001 From: Andrew Seguin Date: Fri, 30 Jun 2017 10:09:25 -0700 Subject: [PATCH 01/12] docs(table): initial table docs --- src/cdk/table/table.md | 175 ++++++++++++++++++ src/demo-app/table/table-demo.html | 10 +- src/demo-app/table/table-demo.ts | 12 +- src/material-examples/example-module.ts | 17 ++ .../table-basic/table-basic-example.css | 48 +++++ .../table-basic/table-basic-example.html | 37 ++++ .../table-basic/table-basic-example.ts | 89 +++++++++ .../table-filtering-example.css | 63 +++++++ .../table-filtering-example.html | 43 +++++ .../table-filtering-example.ts | 121 ++++++++++++ .../table-overview/table-overview-example.css | 1 + .../table-overview-example.html | 1 + .../table-overview/table-overview-example.ts | 10 + .../table-pagination-example.css | 48 +++++ .../table-pagination-example.html | 44 +++++ .../table-pagination-example.ts | 103 +++++++++++ .../table-sorting/table-sorting-example.css | 52 ++++++ .../table-sorting/table-sorting-example.html | 37 ++++ .../table-sorting/table-sorting-example.ts | 122 ++++++++++++ src/material-examples/tsconfig-build.json | 3 +- tools/gulp/gulpfile.ts | 2 +- tools/gulp/tasks/docs.ts | 2 +- 22 files changed, 1026 insertions(+), 14 deletions(-) create mode 100644 src/cdk/table/table.md create mode 100644 src/material-examples/table-basic/table-basic-example.css create mode 100644 src/material-examples/table-basic/table-basic-example.html create mode 100644 src/material-examples/table-basic/table-basic-example.ts create mode 100644 src/material-examples/table-filtering/table-filtering-example.css create mode 100644 src/material-examples/table-filtering/table-filtering-example.html create mode 100644 src/material-examples/table-filtering/table-filtering-example.ts create mode 100644 src/material-examples/table-overview/table-overview-example.css create mode 100644 src/material-examples/table-overview/table-overview-example.html create mode 100644 src/material-examples/table-overview/table-overview-example.ts create mode 100644 src/material-examples/table-pagination/table-pagination-example.css create mode 100644 src/material-examples/table-pagination/table-pagination-example.html create mode 100644 src/material-examples/table-pagination/table-pagination-example.ts create mode 100644 src/material-examples/table-sorting/table-sorting-example.css create mode 100644 src/material-examples/table-sorting/table-sorting-example.html create mode 100644 src/material-examples/table-sorting/table-sorting-example.ts diff --git a/src/cdk/table/table.md b/src/cdk/table/table.md new file mode 100644 index 000000000000..d9a863610063 --- /dev/null +++ b/src/cdk/table/table.md @@ -0,0 +1,175 @@ +The CDK Data Table displays rows of data with fully customizable cell templates. +Its single responsibility is the efficient rendering of rows in a fully accessible way. + +The CDK table provides a foundation upon which other features, such as sorting and pagination, can be built. +Because the CDK table enforces no opinions on these matters, developers have full control over the interaction patterns associated with the table. + +For a Material Design styled table, see ``, which builds on top of the CDK Data Table. + +In the near future, the material library will include an additional "simple table", +building `` with a more minimal interface and sorting, pagination, and selection built-in. + + + +## Using the CDK Data Table + +### Writing your table template + +The first step to writing the CDK Data Table template is to define the columns that will be used in your table. +Each column definition will consist of a header cell template and a data cell template by using +the `` and ``, respectively. These will be wrapped in an `` and given a column name. + +Both the `` and `` require an additional directive so that the table can +capture the inner template. For `` you must include the attribute `*cdkHeaderCellDef` +and for `` you must include `*cdkCellDef`. Note that the `*cdkCellDef` provides an outlet +to capture the cell’s row data to be used in the template. + +```html + + Column A + {{row.a}} + +``` + +After the columns have been defined, you must include a `` and `` which will +each take an array of the column names. This will be the columns that will be rendered in the table and in the order provided. + +```html + + +``` + +In the following template, we have a data table that displays three columns: Column A, Column B, and Column C. +The and are given an input of what columns to display. + +```html + + + + Column A + {{row.a}} + + + + + Column B + {{row.b}} + + + + + Column C + {{row.c}} + + + + + + +``` + +It is not required to display all the columns that are defined within the template, +nor is the order required. For example, if we wanted the table to display only Column B +and Column A and in that order, then the template would look like this: + +```html + + +``` + +Adding attribute and event binding to the header and rows is as simple as applying them to the + and . For example, here the table is adding a click handler to both. +In addition, the CSS class `a-bigger-than-twenty` will be applied to any row where its data’s `a` property is greater than 20. + +```html + + + + 20” + (click)=”handleRowClick(row)”> + +``` + +Changing the list of columns provided to the `` and `` will automatically +cause the table to re-render to reflect those changes. For more information, see Dynamic Columns below under Features. + +### Connecting the table to a data source +Data is provided to the table through the `DataSource` interface. When the table receives a DataSource, +it calls its connect function to receive an observable that emits an array of data. Whenever the Data Source emits data to this stream, the table will use it to render its rows. + +Since the Data Source provides this data stream, it is responsible for watching for data changes +and notifying the table when to re-render. Examples of these data changes includes sorting, pagination, filtering, and more. +To see how these examples can be incorporated in the Data Source, see below under Features. + +Note that a trackBy function can be provided to the table similar to Angular’s ngFor trackBy. +This allows you to customize how the table to identifies rows and improves performance. + +In the future, the connect function will be able to use the CollectionViewer parameter to be +notified about table events, such as what rows the user is currently viewing. This could be used to +help the Data Source know what data does not need to be retrieved and rendered, further improving performance. + +## Material Table +To use the CDK Data Table with styles matching the Material Design spec, you can use the `` +defined in `@angular/material`. This will build on the CDK Data Table and apply built-in Material Design styles. + +The interface for the `` matches the ``, except that its element selectors +will be prefixed with `md-` instead of `cdk-`. + +Note that the column definition directives (`cdkColumnDef` and `cdkHeaderCellDef`) are still prefixed with `cdk-`. + +```html + + + + Column A + {{row.a}} + + + + + Column B + {{row.b}} + + + + + Column C + {{row.c}} + + + + + + +``` + +## Simple Table + +In the near future, we would like to provide a simple version of the data table that includes an easy-to-use interface, +material styling, data array input, and out-of-the-box features such as sorting, pagination, and selection. + +## Features + +The CDK Table’s responsibility is to handle efficient rendering of rows and it’s the Data Source’s job +to let the table know what data should be rendered. As such, features that manipulate what data should +be rendered should be the responsibility of the data source. + +### Pagination +Use the MdPagination component to add data paging to the data table. The data source can listen to +paging events from the component and appropriately slice the right data from whatever data provider +is used. Sending this new data to the table will cause it to render the new page of data. + + + +### Sorting +Use the MdSort component to enable sorting the table's data through the column headers. +The data source can listen to sorting events from the component and sort the data before giving it +to the table to render. + + + +### Filtering + + \ No newline at end of file diff --git a/src/demo-app/table/table-demo.html b/src/demo-app/table/table-demo.html index 403a04f2b8a8..11d0a5d601ce 100644 --- a/src/demo-app/table/table-demo.html +++ b/src/demo-app/table/table-demo.html @@ -76,8 +76,8 @@

CdkTable Example

{{row.color}}
- - + - @@ -130,8 +130,8 @@

MdTable Example

{{row.color}} - - + +
diff --git a/src/demo-app/table/table-demo.ts b/src/demo-app/table/table-demo.ts index 9bb1050b4fa1..86e6a3301c7c 100644 --- a/src/demo-app/table/table-demo.ts +++ b/src/demo-app/table/table-demo.ts @@ -16,7 +16,7 @@ export type TrackByStrategy = 'id' | 'reference' | 'index'; }) export class TableDemo { dataSource: PersonDataSource | null; - propertiesToDisplay: UserProperties[] = []; + displayedColumns: UserProperties[] = []; trackByStrategy: TrackByStrategy = 'reference'; changeReferences = false; highlights = new Set(); @@ -32,7 +32,7 @@ export class TableDemo { } connect() { - this.propertiesToDisplay = ['userId', 'userName', 'progress', 'color']; + this.displayedColumns = ['userId', 'userName', 'progress', 'color']; this.dataSource = new PersonDataSource(this._peopleDatabase, this._paginator, this.sort); this._peopleDatabase.initialize(); @@ -40,7 +40,7 @@ export class TableDemo { disconnect() { this.dataSource = null; - this.propertiesToDisplay = []; + this.displayedColumns = []; } getOpacity(progress: number) { @@ -57,11 +57,11 @@ export class TableDemo { } toggleColorColumn() { - let colorColumnIndex = this.propertiesToDisplay.indexOf('color'); + let colorColumnIndex = this.displayedColumns.indexOf('color'); if (colorColumnIndex == -1) { - this.propertiesToDisplay.push('color'); + this.displayedColumns.push('color'); } else { - this.propertiesToDisplay.splice(colorColumnIndex, 1); + this.displayedColumns.splice(colorColumnIndex, 1); } } diff --git a/src/material-examples/example-module.ts b/src/material-examples/example-module.ts index 3df3fbf58a05..2e974f90bf54 100644 --- a/src/material-examples/example-module.ts +++ b/src/material-examples/example-module.ts @@ -91,6 +91,12 @@ import { MdRadioModule, MdSelectModule, MdSidenavModule, MdSliderModule, MdSlideToggleModule, MdSnackBarModule, MdTabsModule, MdToolbarModule, MdTooltipModule } from '@angular/material'; +import {CdkTableModule} from '@angular/cdk'; +import {TableOverviewExample} from './table-overview/table-overview-example'; +import {TablePaginationExample} from './table-pagination/table-pagination-example'; +import {TableBasicExample} from './table-basic/table-basic-example'; +import {TableSortingExample} from './table-sorting/table-sorting-example'; +import {TableFilteringExample} from './table-filtering/table-filtering-example'; export interface LiveExample { title: string; @@ -194,6 +200,11 @@ export const EXAMPLE_COMPONENTS = { component: SnackBarComponentExample }, 'snack-bar-overview': {title: 'Basic snack-bar', component: SnackBarOverviewExample}, + 'table-overview': {title: 'Feature-rich data table', component: TableOverviewExample}, + 'table-pagination': {title: 'Table with pagination', component: TablePaginationExample}, + 'table-sorting': {title: 'Table with sorting', component: TableSortingExample}, + 'table-filtering': {title: 'Table with filtering', component: TableFilteringExample}, + 'table-basic': {title: 'Basic table', component: TableBasicExample}, 'tabs-overview': {title: 'Basic tabs', component: TabsOverviewExample}, 'tabs-template-label': {title: 'Coming soon!', component: TabsTemplateLabelExample}, 'toolbar-multirow': {title: 'Multi-row toolbar', component: ToolbarMultirowExample}, @@ -207,6 +218,7 @@ export const EXAMPLE_COMPONENTS = { */ @NgModule({ exports: [ + CdkTableModule, MdAutocompleteModule, MdButtonModule, MdButtonToggleModule, @@ -298,6 +310,11 @@ export const EXAMPLE_LIST = [ SnackBarComponentExample, PizzaPartyComponent, SnackBarOverviewExample, + TableBasicExample, + TableOverviewExample, + TableFilteringExample, + TablePaginationExample, + TableSortingExample, TabsOverviewExample, TabsTemplateLabelExample, ToolbarMultirowExample, diff --git a/src/material-examples/table-basic/table-basic-example.css b/src/material-examples/table-basic/table-basic-example.css new file mode 100644 index 000000000000..4da5dfaea774 --- /dev/null +++ b/src/material-examples/table-basic/table-basic-example.css @@ -0,0 +1,48 @@ +/* Structure */ +.example-container { + display: flex; + flex-direction: column; + max-height: 500px; + background: white; + min-width: 300px; +} + +.example-header { + min-height: 64px; + display: flex; + align-items: center; + padding-left: 24px; + font-size: 20px; +} + +/* + * Styles to make the demo's cdk-table match the material design spec + * https://material.io/guidelines/components/data-tables.html + */ +.cdk-table { + flex: 1 1 auto; + overflow: auto; +} + +.cdk-row, .cdk-header-row { + display: flex; + border-bottom: 1px solid #ccc; + align-items: center; + height: 48px; + padding: 0 24px; +} + +.cdk-cell, .cdk-header-cell { + flex: 1; +} + +.cdk-header-cell { + font-size: 12px; + font-weight: bold; + color: rgba(0, 0, 0, 0.54); +} + +.cdk-cell { + font-size: 13px; + color: rgba(0, 0, 0, 0.87); +} \ No newline at end of file diff --git a/src/material-examples/table-basic/table-basic-example.html b/src/material-examples/table-basic/table-basic-example.html new file mode 100644 index 000000000000..b6d597bef2f4 --- /dev/null +++ b/src/material-examples/table-basic/table-basic-example.html @@ -0,0 +1,37 @@ +
+
Users
+ + + + + + + + ID + {{row.id}} + + + + + Progress + {{row.progress}}% + + + + + Name + {{row.name}} + + + + + Color + {{row.color}} + + + + + + +
\ No newline at end of file diff --git a/src/material-examples/table-basic/table-basic-example.ts b/src/material-examples/table-basic/table-basic-example.ts new file mode 100644 index 000000000000..1e0d1f88e757 --- /dev/null +++ b/src/material-examples/table-basic/table-basic-example.ts @@ -0,0 +1,89 @@ +import {Component} from '@angular/core'; +import {DataSource} from '@angular/cdk'; +import {BehaviorSubject} from 'rxjs/BehaviorSubject'; +import {Observable} from 'rxjs/Observable'; +import 'rxjs/add/operator/startWith'; +import 'rxjs/add/observable/merge'; +import 'rxjs/add/operator/map'; + +@Component({ + selector: 'table-basic-example', + styleUrls: ['table-basic-example.css'], + templateUrl: 'table-basic-example.html', +}) +export class TableBasicExample { + displayedColumns = ['userId', 'userName', 'progress', 'color']; + exampleDatabase = new ExampleDatabase(); + dataSource: ExampleDataSource | null; + + ngOnInit() { + this.dataSource = new ExampleDataSource(this.exampleDatabase); + } +} + +/** Constants used to fill up our data base. */ +const COLORS = ['maroon', 'red', 'orange', 'yellow', 'olive', 'green', 'purple', + 'fuchsia', 'lime', 'teal', 'aqua', 'blue', 'navy', 'black', 'gray']; +const NAMES = ['Maia', 'Asher', 'Olivia', 'Atticus', 'Amelia', 'Jack', + 'Charlotte', 'Theodore', 'Isla', 'Oliver', 'Isabella', 'Jasper', + 'Cora', 'Levi', 'Violet', 'Arthur', 'Mia', 'Thomas', 'Elizabeth']; + +export interface UserData { + id: string; + name: string; + progress: string; + color: string; +} + +/** An example database that the data source uses to retrieve data for the table. */ +export class ExampleDatabase { + /** Stream that emits whenever the data has been modified. */ + dataChange: BehaviorSubject = new BehaviorSubject([]); + get data(): UserData[] { return this.dataChange.value; } + + constructor() { + // Fill up the database with 100 users. + for (let i = 0; i < 100; i++) { this.addUser(); } + } + + /** Adds a new user to the database. */ + addUser() { + const copiedData = this.data.slice(); + copiedData.push(this.createNewUser()); + this.dataChange.next(copiedData); + } + + /** Builds and returns a new User. */ + private createNewUser() { + const name = + NAMES[Math.round(Math.random() * (NAMES.length - 1))] + ' ' + + NAMES[Math.round(Math.random() * (NAMES.length - 1))].charAt(0) + '.'; + + return { + id: (this.data.length + 1).toString(), + name: name, + progress: Math.round(Math.random() * 100).toString(), + color: COLORS[Math.round(Math.random() * (COLORS.length - 1))] + }; + } +} + +/** + * Data source to provide what data should be rendered in the table. Note that the data source + * can retrieve its data in any way. In this case, the data source is provided a reference + * to a common data base, ExampleDatabase. It is not the data source's responsibility to manage + * the underlying data. Instead, it only needs to take the data and send the table exactly what + * should be rendered. + */ +export class ExampleDataSource extends DataSource { + constructor(private _exampleDatabase: ExampleDatabase) { + super(); + } + + /** Connect function called by the table to retrieve one stream containing the data to render. */ + connect(): Observable { + return this._exampleDatabase.dataChange; + } + + disconnect() {} +} diff --git a/src/material-examples/table-filtering/table-filtering-example.css b/src/material-examples/table-filtering/table-filtering-example.css new file mode 100644 index 000000000000..08398d06df0a --- /dev/null +++ b/src/material-examples/table-filtering/table-filtering-example.css @@ -0,0 +1,63 @@ +/* Structure */ +.example-container { + display: flex; + flex-direction: column; + max-height: 500px; + background: white; + min-width: 300px; +} + +.example-header { + min-height: 64px; + display: flex; + align-items: center; + padding-left: 24px; + font-size: 20px; +} + +.example-header { + min-height: 64px; + display: flex; + align-items: baseline; + padding: 8px 24px 0 24px; + font-size: 20px; + justify-content: space-between; +} + +.mat-input-container { + font-size: 14px; + flex-grow: 1; + margin-left: 32px; +} + +/* + * Styles to make the demo's cdk-table match the material design spec + * https://material.io/guidelines/components/data-tables.html + */ +.cdk-table { + flex: 1 1 auto; + overflow: auto; +} + +.cdk-row, .cdk-header-row { + display: flex; + border-bottom: 1px solid #ccc; + align-items: center; + height: 48px; + padding: 0 24px; +} + +.cdk-cell, .cdk-header-cell { + flex: 1; +} + +.cdk-header-cell { + font-size: 12px; + font-weight: bold; + color: rgba(0, 0, 0, 0.54); +} + +.cdk-cell { + font-size: 13px; + color: rgba(0, 0, 0, 0.87); +} \ No newline at end of file diff --git a/src/material-examples/table-filtering/table-filtering-example.html b/src/material-examples/table-filtering/table-filtering-example.html new file mode 100644 index 000000000000..cfed5b4a0e73 --- /dev/null +++ b/src/material-examples/table-filtering/table-filtering-example.html @@ -0,0 +1,43 @@ +
+
+ Users + + + + +
+ + + + + + + + ID + {{row.id}} + + + + + Progress + {{row.progress}}% + + + + + Name + {{row.name}} + + + + + Color + {{row.color}} + + + + + + +
\ No newline at end of file diff --git a/src/material-examples/table-filtering/table-filtering-example.ts b/src/material-examples/table-filtering/table-filtering-example.ts new file mode 100644 index 000000000000..8210e4a32027 --- /dev/null +++ b/src/material-examples/table-filtering/table-filtering-example.ts @@ -0,0 +1,121 @@ +import {Component, ElementRef, ViewChild} from '@angular/core'; +import {DataSource} from '@angular/cdk'; +import {MdSort} from '@angular/material'; +import {BehaviorSubject} from 'rxjs/BehaviorSubject'; +import {Observable} from 'rxjs/Observable'; +import 'rxjs/add/operator/startWith'; +import 'rxjs/add/observable/merge'; +import 'rxjs/add/operator/map'; +import 'rxjs/add/operator/debounceTime'; +import 'rxjs/add/operator/distinctUntilChanged'; +import 'rxjs/add/observable/fromEvent'; + +@Component({ + selector: 'table-filtering-example', + styleUrls: ['table-filtering-example.css'], + templateUrl: 'table-filtering-example.html', +}) +export class TableFilteringExample { + displayedColumns = ['userId', 'userName', 'progress', 'color']; + exampleDatabase = new ExampleDatabase(); + dataSource: ExampleDataSource | null; + + @ViewChild('filter') filter: ElementRef; + + ngOnInit() { + this.dataSource = new ExampleDataSource(this.exampleDatabase); + Observable.fromEvent(this.filter.nativeElement, 'keyup') + .debounceTime(150) + .distinctUntilChanged() + .subscribe(() => { + if (!this.dataSource) { return; } + this.dataSource.filter = this.filter.nativeElement.value; + }); + } +} + +/** Constants used to fill up our data base. */ +const COLORS = ['maroon', 'red', 'orange', 'yellow', 'olive', 'green', 'purple', + 'fuchsia', 'lime', 'teal', 'aqua', 'blue', 'navy', 'black', 'gray']; +const NAMES = ['Maia', 'Asher', 'Olivia', 'Atticus', 'Amelia', 'Jack', + 'Charlotte', 'Theodore', 'Isla', 'Oliver', 'Isabella', 'Jasper', + 'Cora', 'Levi', 'Violet', 'Arthur', 'Mia', 'Thomas', 'Elizabeth']; + +export interface UserData { + id: string; + name: string; + progress: string; + color: string; +} + +/** An example database that the data source uses to retrieve data for the table. */ +export class ExampleDatabase { + /** Stream that emits whenever the data has been modified. */ + dataChange: BehaviorSubject = new BehaviorSubject([]); + get data(): UserData[] { return this.dataChange.value; } + + constructor() { + // Fill up the database with 100 users. + for (let i = 0; i < 100; i++) { this.addUser(); } + } + + /** Adds a new user to the database. */ + addUser() { + const copiedData = this.data.slice(); + copiedData.push(this.createNewUser()); + this.dataChange.next(copiedData); + } + + /** Builds and returns a new User. */ + private createNewUser() { + const name = + NAMES[Math.round(Math.random() * (NAMES.length - 1))] + ' ' + + NAMES[Math.round(Math.random() * (NAMES.length - 1))].charAt(0) + '.'; + + return { + id: (this.data.length + 1).toString(), + name: name, + progress: Math.round(Math.random() * 100).toString(), + color: COLORS[Math.round(Math.random() * (COLORS.length - 1))] + }; + } +} + +/** + * Data source to provide what data should be rendered in the table. Note that the data source + * can retrieve its data in any way. In this case, the data source is provided a reference + * to a common data base, ExampleDatabase. It is not the data source's responsibility to manage + * the underlying data. Instead, it only needs to take the data and send the table exactly what + * should be rendered. + */ +export class ExampleDataSource extends DataSource { + _filterChange = new BehaviorSubject(''); + get filter(): string { return this._filterChange.value; } + set filter(filter: string) { this._filterChange.next(filter); } + + constructor(private _exampleDatabase: ExampleDatabase) { + super(); + } + + /** Connect function called by the table to retrieve one stream containing the data to render. */ + connect(): Observable { + const displayDataChanges = [ + this._exampleDatabase.dataChange, + this._filterChange, + ]; + + return Observable.merge(...displayDataChanges).map(() => { + return this._exampleDatabase.data.slice().filter((item: UserData) => { + let searchStr = (item.name + item.color).toLowerCase(); + return searchStr.indexOf(this.filter.toLowerCase()) != -1; + }); + }); + } + + disconnect() {} +} + + +/** Copyright 2017 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 http://angular.io/license */ \ No newline at end of file diff --git a/src/material-examples/table-overview/table-overview-example.css b/src/material-examples/table-overview/table-overview-example.css new file mode 100644 index 000000000000..7432308753e6 --- /dev/null +++ b/src/material-examples/table-overview/table-overview-example.css @@ -0,0 +1 @@ +/** No CSS for this example */ diff --git a/src/material-examples/table-overview/table-overview-example.html b/src/material-examples/table-overview/table-overview-example.html new file mode 100644 index 000000000000..182483349dcb --- /dev/null +++ b/src/material-examples/table-overview/table-overview-example.html @@ -0,0 +1 @@ +Table example coming soon \ No newline at end of file diff --git a/src/material-examples/table-overview/table-overview-example.ts b/src/material-examples/table-overview/table-overview-example.ts new file mode 100644 index 000000000000..4bf2c5266b92 --- /dev/null +++ b/src/material-examples/table-overview/table-overview-example.ts @@ -0,0 +1,10 @@ +import {Component} from '@angular/core'; + + +@Component({ + selector: 'table-overview-example', + templateUrl: 'table-overview-example.html', + styleUrls: ['table-overview-example.css'], +}) +export class TableOverviewExample { +} diff --git a/src/material-examples/table-pagination/table-pagination-example.css b/src/material-examples/table-pagination/table-pagination-example.css new file mode 100644 index 000000000000..4da5dfaea774 --- /dev/null +++ b/src/material-examples/table-pagination/table-pagination-example.css @@ -0,0 +1,48 @@ +/* Structure */ +.example-container { + display: flex; + flex-direction: column; + max-height: 500px; + background: white; + min-width: 300px; +} + +.example-header { + min-height: 64px; + display: flex; + align-items: center; + padding-left: 24px; + font-size: 20px; +} + +/* + * Styles to make the demo's cdk-table match the material design spec + * https://material.io/guidelines/components/data-tables.html + */ +.cdk-table { + flex: 1 1 auto; + overflow: auto; +} + +.cdk-row, .cdk-header-row { + display: flex; + border-bottom: 1px solid #ccc; + align-items: center; + height: 48px; + padding: 0 24px; +} + +.cdk-cell, .cdk-header-cell { + flex: 1; +} + +.cdk-header-cell { + font-size: 12px; + font-weight: bold; + color: rgba(0, 0, 0, 0.54); +} + +.cdk-cell { + font-size: 13px; + color: rgba(0, 0, 0, 0.87); +} \ No newline at end of file diff --git a/src/material-examples/table-pagination/table-pagination-example.html b/src/material-examples/table-pagination/table-pagination-example.html new file mode 100644 index 000000000000..e32a83efb3a5 --- /dev/null +++ b/src/material-examples/table-pagination/table-pagination-example.html @@ -0,0 +1,44 @@ +
+
Users
+ + + + + + + + ID + {{row.id}} + + + + + Progress + {{row.progress}}% + + + + + Name + {{row.name}} + + + + + Color + {{row.color}} + + + + + + + + + +
\ No newline at end of file diff --git a/src/material-examples/table-pagination/table-pagination-example.ts b/src/material-examples/table-pagination/table-pagination-example.ts new file mode 100644 index 000000000000..730b0437355d --- /dev/null +++ b/src/material-examples/table-pagination/table-pagination-example.ts @@ -0,0 +1,103 @@ +import {Component, ViewChild} from '@angular/core'; +import {DataSource} from '@angular/cdk'; +import {MdPaginator} from '@angular/material'; +import {BehaviorSubject} from 'rxjs/BehaviorSubject'; +import {Observable} from 'rxjs/Observable'; +import 'rxjs/add/operator/startWith'; +import 'rxjs/add/observable/merge'; +import 'rxjs/add/operator/map'; + +@Component({ + selector: 'table-pagination-example', + styleUrls: ['table-pagination-example.css'], + templateUrl: 'table-pagination-example.html', +}) +export class TablePaginationExample { + displayedColumns = ['userId', 'userName', 'progress', 'color']; + exampleDatabase = new ExampleDatabase(); + dataSource: ExampleDataSource | null; + + @ViewChild(MdPaginator) paginator: MdPaginator; + + ngOnInit() { + this.dataSource = new ExampleDataSource(this.exampleDatabase, this.paginator); + } +} + +/** Constants used to fill up our data base. */ +const COLORS = ['maroon', 'red', 'orange', 'yellow', 'olive', 'green', 'purple', + 'fuchsia', 'lime', 'teal', 'aqua', 'blue', 'navy', 'black', 'gray']; +const NAMES = ['Maia', 'Asher', 'Olivia', 'Atticus', 'Amelia', 'Jack', + 'Charlotte', 'Theodore', 'Isla', 'Oliver', 'Isabella', 'Jasper', + 'Cora', 'Levi', 'Violet', 'Arthur', 'Mia', 'Thomas', 'Elizabeth']; + +export interface UserData { + id: string; + name: string; + progress: string; + color: string; +} + +/** An example database that the data source uses to retrieve data for the table. */ +export class ExampleDatabase { + /** Stream that emits whenever the data has been modified. */ + dataChange: BehaviorSubject = new BehaviorSubject([]); + get data(): UserData[] { return this.dataChange.value; } + + constructor() { + // Fill up the database with 100 users. + for (let i = 0; i < 100; i++) { this.addUser(); } + } + + /** Adds a new user to the database. */ + addUser() { + const copiedData = this.data.slice(); + copiedData.push(this.createNewUser()); + this.dataChange.next(copiedData); + } + + /** Builds and returns a new User. */ + private createNewUser() { + const name = + NAMES[Math.round(Math.random() * (NAMES.length - 1))] + ' ' + + NAMES[Math.round(Math.random() * (NAMES.length - 1))].charAt(0) + '.'; + + return { + id: (this.data.length + 1).toString(), + name: name, + progress: Math.round(Math.random() * 100).toString(), + color: COLORS[Math.round(Math.random() * (COLORS.length - 1))] + }; + } +} + +/** + * Data source to provide what data should be rendered in the table. Note that the data source + * can retrieve its data in any way. In this case, the data source is provided a reference + * to a common data base, ExampleDatabase. It is not the data source's responsibility to manage + * the underlying data. Instead, it only needs to take the data and send the table exactly what + * should be rendered. + */ +export class ExampleDataSource extends DataSource { + constructor(private _exampleDatabase: ExampleDatabase, private _paginator: MdPaginator) { + super(); + } + + /** Connect function called by the table to retrieve one stream containing the data to render. */ + connect(): Observable { + const displayDataChanges = [ + this._exampleDatabase.dataChange, + this._paginator.page, + ]; + + return Observable.merge(...displayDataChanges).map(() => { + const data = this._exampleDatabase.data.slice(); + + // Grab the page's slice of data. + const startIndex = this._paginator.pageIndex * this._paginator.pageSize; + return data.splice(startIndex, this._paginator.pageSize); + }); + } + + disconnect() {} +} diff --git a/src/material-examples/table-sorting/table-sorting-example.css b/src/material-examples/table-sorting/table-sorting-example.css new file mode 100644 index 000000000000..add0ff3c9246 --- /dev/null +++ b/src/material-examples/table-sorting/table-sorting-example.css @@ -0,0 +1,52 @@ +/* Structure */ +.example-container { + display: flex; + flex-direction: column; + max-height: 500px; + background: white; + min-width: 300px; +} + +.example-header { + min-height: 64px; + display: flex; + align-items: center; + padding-left: 24px; + font-size: 20px; +} + +.cdk-header-cell .mat-sort-header-sorted { + color: black; +} + +/* + * Styles to make the demo's cdk-table match the material design spec + * https://material.io/guidelines/components/data-tables.html + */ +.cdk-table { + flex: 1 1 auto; + overflow: auto; +} + +.cdk-row, .cdk-header-row { + display: flex; + border-bottom: 1px solid #ccc; + align-items: center; + height: 48px; + padding: 0 24px; +} + +.cdk-cell, .cdk-header-cell { + flex: 1; +} + +.cdk-header-cell { + font-size: 12px; + font-weight: bold; + color: rgba(0, 0, 0, 0.54); +} + +.cdk-cell { + font-size: 13px; + color: rgba(0, 0, 0, 0.87); +} \ No newline at end of file diff --git a/src/material-examples/table-sorting/table-sorting-example.html b/src/material-examples/table-sorting/table-sorting-example.html new file mode 100644 index 000000000000..ea60819ecdce --- /dev/null +++ b/src/material-examples/table-sorting/table-sorting-example.html @@ -0,0 +1,37 @@ +
+
Users
+ + + + + + + + ID + {{row.id}} + + + + + Progress + {{row.progress}}% + + + + + Name + {{row.name}} + + + + + Color + {{row.color}} + + + + + + +
\ No newline at end of file diff --git a/src/material-examples/table-sorting/table-sorting-example.ts b/src/material-examples/table-sorting/table-sorting-example.ts new file mode 100644 index 000000000000..9578c59b1172 --- /dev/null +++ b/src/material-examples/table-sorting/table-sorting-example.ts @@ -0,0 +1,122 @@ +import {Component, ViewChild} from '@angular/core'; +import {DataSource} from '@angular/cdk'; +import {MdSort} from '@angular/material'; +import {BehaviorSubject} from 'rxjs/BehaviorSubject'; +import {Observable} from 'rxjs/Observable'; +import 'rxjs/add/operator/startWith'; +import 'rxjs/add/observable/merge'; +import 'rxjs/add/operator/map'; + +@Component({ + selector: 'table-sorting-example', + styleUrls: ['table-sorting-example.css'], + templateUrl: 'table-sorting-example.html', +}) +export class TableSortingExample { + displayedColumns = ['userId', 'userName', 'progress', 'color']; + exampleDatabase = new ExampleDatabase(); + dataSource: ExampleDataSource | null; + + @ViewChild(MdSort) sort: MdSort; + + ngOnInit() { + this.dataSource = new ExampleDataSource(this.exampleDatabase, this.sort); + } +} + +/** Constants used to fill up our data base. */ +const COLORS = ['maroon', 'red', 'orange', 'yellow', 'olive', 'green', 'purple', + 'fuchsia', 'lime', 'teal', 'aqua', 'blue', 'navy', 'black', 'gray']; +const NAMES = ['Maia', 'Asher', 'Olivia', 'Atticus', 'Amelia', 'Jack', + 'Charlotte', 'Theodore', 'Isla', 'Oliver', 'Isabella', 'Jasper', + 'Cora', 'Levi', 'Violet', 'Arthur', 'Mia', 'Thomas', 'Elizabeth']; + +export interface UserData { + id: string; + name: string; + progress: string; + color: string; +} + +/** An example database that the data source uses to retrieve data for the table. */ +export class ExampleDatabase { + /** Stream that emits whenever the data has been modified. */ + dataChange: BehaviorSubject = new BehaviorSubject([]); + get data(): UserData[] { return this.dataChange.value; } + + constructor() { + // Fill up the database with 100 users. + for (let i = 0; i < 100; i++) { this.addUser(); } + } + + /** Adds a new user to the database. */ + addUser() { + const copiedData = this.data.slice(); + copiedData.push(this.createNewUser()); + this.dataChange.next(copiedData); + } + + /** Builds and returns a new User. */ + private createNewUser() { + const name = + NAMES[Math.round(Math.random() * (NAMES.length - 1))] + ' ' + + NAMES[Math.round(Math.random() * (NAMES.length - 1))].charAt(0) + '.'; + + return { + id: (this.data.length + 1).toString(), + name: name, + progress: Math.round(Math.random() * 100).toString(), + color: COLORS[Math.round(Math.random() * (COLORS.length - 1))] + }; + } +} + +/** + * Data source to provide what data should be rendered in the table. Note that the data source + * can retrieve its data in any way. In this case, the data source is provided a reference + * to a common data base, ExampleDatabase. It is not the data source's responsibility to manage + * the underlying data. Instead, it only needs to take the data and send the table exactly what + * should be rendered. + */ +export class ExampleDataSource extends DataSource { + constructor(private _exampleDatabase: ExampleDatabase, private _sort: MdSort) { + super(); + } + + /** Connect function called by the table to retrieve one stream containing the data to render. */ + connect(): Observable { + const displayDataChanges = [ + this._exampleDatabase.dataChange, + this._sort.mdSortChange, + ]; + + return Observable.merge(...displayDataChanges).map(() => { + return this.getSortedData(); + }); + } + + disconnect() {} + + /** Returns a sorted copy of the database data. */ + getSortedData(): UserData[] { + const data = this._exampleDatabase.data.slice(); + if (!this._sort.active || this._sort.direction == '') { return data; } + + return data.sort((a, b) => { + let propertyA: number|string = ''; + let propertyB: number|string = ''; + + switch (this._sort.active) { + case 'userId': [propertyA, propertyB] = [a.id, b.id]; break; + case 'userName': [propertyA, propertyB] = [a.name, b.name]; break; + case 'progress': [propertyA, propertyB] = [a.progress, b.progress]; break; + case 'color': [propertyA, propertyB] = [a.color, b.color]; break; + } + + let valueA = isNaN(+propertyA) ? propertyA : +propertyA; + let valueB = isNaN(+propertyB) ? propertyB : +propertyB; + + return (valueA < valueB ? -1 : 1) * (this._sort.direction == 'asc' ? 1 : -1); + }); + } +} diff --git a/src/material-examples/tsconfig-build.json b/src/material-examples/tsconfig-build.json index 56a129b4ab81..fca6a83f5b30 100644 --- a/src/material-examples/tsconfig-build.json +++ b/src/material-examples/tsconfig-build.json @@ -20,7 +20,8 @@ "types": [], "baseUrl": ".", "paths": { - "@angular/material": ["../../dist/packages/material/public_api"] + "@angular/material": ["../../dist/packages/material/public_api"], + "@angular/cdk": ["../../dist/packages/cdk/public_api"] } }, "files": [ diff --git a/tools/gulp/gulpfile.ts b/tools/gulp/gulpfile.ts index bd158374ca9d..846869fa8465 100644 --- a/tools/gulp/gulpfile.ts +++ b/tools/gulp/gulpfile.ts @@ -3,7 +3,7 @@ import {createPackageBuildTasks} from 'material2-build-tools'; // Create gulp tasks to build the different packages in the project. createPackageBuildTasks('cdk'); createPackageBuildTasks('material', ['cdk']); -createPackageBuildTasks('material-examples', ['material']); +createPackageBuildTasks('material-examples', ['material', 'cdk']); import './tasks/ci'; import './tasks/clean'; diff --git a/tools/gulp/tasks/docs.ts b/tools/gulp/tasks/docs.ts index 1ae20de8d9af..840ddbc17277 100644 --- a/tools/gulp/tasks/docs.ts +++ b/tools/gulp/tasks/docs.ts @@ -69,7 +69,7 @@ task('docs', [ /** Generates html files from the markdown overviews and guides. */ task('markdown-docs', () => { - return src(['src/lib/**/*.md', 'guides/*.md']) + return src(['src/lib/**/*.md', 'src/cdk/**/*.md', 'guides/*.md']) .pipe(markdown({ // Add syntax highlight using highlight.js highlight: (code: string, language: string) => { From 3cc7509a7e68235cb6870702fa5cecceaccc134f Mon Sep 17 00:00:00 2001 From: Andrew Seguin Date: Fri, 30 Jun 2017 10:10:36 -0700 Subject: [PATCH 02/12] add filtering msg --- src/cdk/table/table.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/cdk/table/table.md b/src/cdk/table/table.md index d9a863610063..b971f6a35546 100644 --- a/src/cdk/table/table.md +++ b/src/cdk/table/table.md @@ -172,4 +172,7 @@ to the table to render. ### Filtering +Apply filtering to your table's data by listening to an input's changes. +When a change occurs, filter the data in the data source and send it to the table to render. + \ No newline at end of file From 5186c3ceaf33c5f1b5169268d99ef127931ff9b4 Mon Sep 17 00:00:00 2001 From: Andrew Seguin Date: Fri, 30 Jun 2017 13:28:20 -0700 Subject: [PATCH 03/12] add overview --- src/cdk/table/table.md | 5 +- src/material-examples/example-module.ts | 3 +- .../table-overview/table-overview-example.css | 85 ++++++++- .../table-overview-example.html | 80 +++++++- .../table-overview/table-overview-example.ts | 176 +++++++++++++++++- 5 files changed, 341 insertions(+), 8 deletions(-) diff --git a/src/cdk/table/table.md b/src/cdk/table/table.md index b971f6a35546..f6550e132fc9 100644 --- a/src/cdk/table/table.md +++ b/src/cdk/table/table.md @@ -78,8 +78,9 @@ and Column A and in that order, then the template would look like this: ``` Adding attribute and event binding to the header and rows is as simple as applying them to the - and . For example, here the table is adding a click handler to both. -In addition, the CSS class `a-bigger-than-twenty` will be applied to any row where its data’s `a` property is greater than 20. +`` and ``. For example, here the table is adding a click handler to both. +In addition, the CSS class `a-bigger-than-twenty` will be applied to any row where its data’s `a` +property is greater than 20. ```html +
+ Users + + + + +
+
+ {{selection.selected.length}} + {{selection.selected.length == 1 ? 'user' : 'users'}} + selected +
+ + + + + + + + + + + + + + + + + + + + ID + {{row.id}} + + + + + Progress + {{row.progress}}% + + + + + Name + {{row.name}} + + + + + Color + {{row.color}} + + + + + + + +
+ No users found matching filter. +
+ + + + diff --git a/src/material-examples/table-overview/table-overview-example.ts b/src/material-examples/table-overview/table-overview-example.ts index 4bf2c5266b92..37725ef42c2b 100644 --- a/src/material-examples/table-overview/table-overview-example.ts +++ b/src/material-examples/table-overview/table-overview-example.ts @@ -1,10 +1,180 @@ -import {Component} from '@angular/core'; - +import {Component, ElementRef, ViewChild} from '@angular/core'; +import {DataSource} from '@angular/cdk'; +import {MdPaginator, MdSort, SelectionModel} from '@angular/material'; +import {BehaviorSubject} from 'rxjs/BehaviorSubject'; +import {Observable} from 'rxjs/Observable'; +import 'rxjs/add/operator/startWith'; +import 'rxjs/add/observable/merge'; +import 'rxjs/add/observable/fromEvent'; +import 'rxjs/add/operator/map'; +import 'rxjs/add/operator/distinctUntilChanged'; +import 'rxjs/add/operator/debounceTime'; @Component({ selector: 'table-overview-example', - templateUrl: 'table-overview-example.html', styleUrls: ['table-overview-example.css'], + templateUrl: 'table-overview-example.html', }) export class TableOverviewExample { + displayedColumns = ['select', 'userId', 'userName', 'progress', 'color']; + exampleDatabase = new ExampleDatabase(); + selection = new SelectionModel(true, []); + dataSource: ExampleDataSource | null; + + @ViewChild(MdPaginator) paginator: MdPaginator; + @ViewChild(MdSort) sort: MdSort; + @ViewChild('filter') filter: ElementRef; + + ngOnInit() { + this.dataSource = new ExampleDataSource(this.exampleDatabase, this.paginator, this.sort); + Observable.fromEvent(this.filter.nativeElement, 'keyup') + .debounceTime(150) + .distinctUntilChanged() + .subscribe(() => { + if (!this.dataSource) { return; } + this.dataSource.filter = this.filter.nativeElement.value; + }); + } + + isAllSelected(): boolean { + if (!this.dataSource) { return false; } + if (this.selection.isEmpty()) { return false; } + + if (this.filter.nativeElement.value) { + return this.selection.selected.length == this.dataSource.renderedData.length; + } else { + return this.selection.selected.length == this.exampleDatabase.data.length; + } + } + + masterToggle() { + if (!this.dataSource) { return; } + + if (this.isAllSelected()) { + this.selection.clear(); + } else if (this.filter.nativeElement.value) { + this.dataSource.renderedData.forEach(data => this.selection.select(data.id)); + } else { + this.exampleDatabase.data.forEach(data => this.selection.select(data.id)); + } + } +} + +/** Constants used to fill up our data base. */ +const COLORS = ['maroon', 'red', 'orange', 'yellow', 'olive', 'green', 'purple', + 'fuchsia', 'lime', 'teal', 'aqua', 'blue', 'navy', 'black', 'gray']; +const NAMES = ['Maia', 'Asher', 'Olivia', 'Atticus', 'Amelia', 'Jack', + 'Charlotte', 'Theodore', 'Isla', 'Oliver', 'Isabella', 'Jasper', + 'Cora', 'Levi', 'Violet', 'Arthur', 'Mia', 'Thomas', 'Elizabeth']; + +export interface UserData { + id: string; + name: string; + progress: string; + color: string; +} + +/** An example database that the data source uses to retrieve data for the table. */ +export class ExampleDatabase { + /** Stream that emits whenever the data has been modified. */ + dataChange: BehaviorSubject = new BehaviorSubject([]); + get data(): UserData[] { return this.dataChange.value; } + + constructor() { + // Fill up the database with 100 users. + for (let i = 0; i < 100; i++) { this.addUser(); } + } + + /** Adds a new user to the database. */ + addUser() { + const copiedData = this.data.slice(); + copiedData.push(this.createNewUser()); + this.dataChange.next(copiedData); + } + + /** Builds and returns a new User. */ + private createNewUser() { + const name = + NAMES[Math.round(Math.random() * (NAMES.length - 1))] + ' ' + + NAMES[Math.round(Math.random() * (NAMES.length - 1))].charAt(0) + '.'; + + return { + id: (this.data.length + 1).toString(), + name: name, + progress: Math.round(Math.random() * 100).toString(), + color: COLORS[Math.round(Math.random() * (COLORS.length - 1))] + }; + } +} + +/** + * Data source to provide what data should be rendered in the table. Note that the data source + * can retrieve its data in any way. In this case, the data source is provided a reference + * to a common data base, ExampleDatabase. It is not the data source's responsibility to manage + * the underlying data. Instead, it only needs to take the data and send the table exactly what + * should be rendered. + */ +export class ExampleDataSource extends DataSource { + _filterChange = new BehaviorSubject(''); + get filter(): string { return this._filterChange.value; } + set filter(filter: string) { this._filterChange.next(filter); } + + renderedData: UserData[] = []; + + constructor(private _exampleDatabase: ExampleDatabase, + private _paginator: MdPaginator, + private _sort: MdSort) { + super(); + } + + /** Connect function called by the table to retrieve one stream containing the data to render. */ + connect(): Observable { + // Listen for any changes in the base data, sorting, filtering, or pagination + const displayDataChanges = [ + this._exampleDatabase.dataChange, + this._sort.mdSortChange, + this._filterChange, + this._paginator.page, + ]; + + return Observable.merge(...displayDataChanges).map(() => { + // Filter data + const filteredData = this._exampleDatabase.data.slice().filter((item: UserData) => { + let searchStr = (item.name + item.color).toLowerCase(); + return searchStr.indexOf(this.filter.toLowerCase()) != -1; + }); + + // Sort filtered data + const sortedData = this.sortData(filteredData); + + // Grab the page's slice of the filtered sorted data. + const startIndex = this._paginator.pageIndex * this._paginator.pageSize; + this.renderedData = sortedData.splice(startIndex, this._paginator.pageSize); + return this.renderedData; + }); + } + + disconnect() {} + + /** Returns a sorted copy of the database data. */ + sortData(data: UserData[]): UserData[] { + if (!this._sort.active || this._sort.direction == '') { return data; } + + return data.sort((a, b) => { + let propertyA: number|string = ''; + let propertyB: number|string = ''; + + switch (this._sort.active) { + case 'userId': [propertyA, propertyB] = [a.id, b.id]; break; + case 'userName': [propertyA, propertyB] = [a.name, b.name]; break; + case 'progress': [propertyA, propertyB] = [a.progress, b.progress]; break; + case 'color': [propertyA, propertyB] = [a.color, b.color]; break; + } + + let valueA = isNaN(+propertyA) ? propertyA : +propertyA; + let valueB = isNaN(+propertyB) ? propertyB : +propertyB; + + return (valueA < valueB ? -1 : 1) * (this._sort.direction == 'asc' ? 1 : -1); + }); + } } From ca04c674ace69c86ab763a0269ec712af482840f Mon Sep 17 00:00:00 2001 From: Andrew Seguin Date: Fri, 30 Jun 2017 13:31:27 -0700 Subject: [PATCH 04/12] fix height --- src/material-examples/table-overview/table-overview-example.css | 1 + 1 file changed, 1 insertion(+) diff --git a/src/material-examples/table-overview/table-overview-example.css b/src/material-examples/table-overview/table-overview-example.css index 054785bf53d9..f63c79970d5f 100644 --- a/src/material-examples/table-overview/table-overview-example.css +++ b/src/material-examples/table-overview/table-overview-example.css @@ -9,6 +9,7 @@ .example-header { min-height: 56px; + max-height: 56px; display: flex; align-items: center; padding: 8px 24px 0 24px; From 304570b9e1636d5e31b3dc6cc1b1d0e30f04240c Mon Sep 17 00:00:00 2001 From: Andrew Seguin Date: Wed, 5 Jul 2017 13:36:49 -0700 Subject: [PATCH 05/12] split cdk table into guide --- src/cdk/table/table.md | 124 +++++------------- src/lib/table/table.md | 43 ++++++ .../table-basic/table-basic-example.css | 30 +---- .../table-basic/table-basic-example.html | 25 ++-- .../table-filtering-example.css | 30 +---- .../table-filtering-example.html | 25 ++-- .../table-overview/table-overview-example.css | 36 +---- .../table-overview-example.html | 34 ++--- .../table-pagination-example.css | 30 +---- .../table-pagination-example.html | 25 ++-- .../table-sorting/table-sorting-example.css | 34 +---- .../table-sorting/table-sorting-example.html | 25 ++-- 12 files changed, 148 insertions(+), 313 deletions(-) create mode 100644 src/lib/table/table.md diff --git a/src/cdk/table/table.md b/src/cdk/table/table.md index f6550e132fc9..1c985d385e8b 100644 --- a/src/cdk/table/table.md +++ b/src/cdk/table/table.md @@ -1,28 +1,23 @@ -The CDK Data Table displays rows of data with fully customizable cell templates. +The CDK data-table displays rows of data with fully customizable cell templates. Its single responsibility is the efficient rendering of rows in a fully accessible way. -The CDK table provides a foundation upon which other features, such as sorting and pagination, can be built. -Because the CDK table enforces no opinions on these matters, developers have full control over the interaction patterns associated with the table. +The table provides a foundation upon which other features, such as sorting and pagination, can be built. +Because it enforces no opinions on these matters, developers have full control over the interaction patterns associated with the table. -For a Material Design styled table, see ``, which builds on top of the CDK Data Table. +For a Material Design styled table, see the documentation for `` which builds on top of the CDK data-table. In the near future, the material library will include an additional "simple table", -building `` with a more minimal interface and sorting, pagination, and selection built-in. - - +building `` with a more minimal interface and sorting, pagination, and selection built-in. ## Using the CDK Data Table ### Writing your table template -The first step to writing the CDK Data Table template is to define the columns that will be used in your table. -Each column definition will consist of a header cell template and a data cell template by using -the `` and ``, respectively. These will be wrapped in an `` and given a column name. +The first step to writing the data-table template is to define the columns. +A column definition is specified via an `` with the `cdkColumnDef` directive, giving +column a name. Each column definition then contains further definitions for both a header-cell +template (`cdkHeaderCellDef`) and a data-cell template (`cdkCellDef`). -Both the `` and `` require an additional directive so that the table can -capture the inner template. For `` you must include the attribute `*cdkHeaderCellDef` -and for `` you must include `*cdkCellDef`. Note that the `*cdkCellDef` provides an outlet -to capture the cell’s row data to be used in the template. ```html @@ -31,14 +26,20 @@ to capture the cell’s row data to be used in the template. ``` -After the columns have been defined, you must include a `` and `` which will -each take an array of the column names. This will be the columns that will be rendered in the table and in the order provided. +Note that `cdkCellDef` exports the row context such that the row data (and additional fields) can +be referenced in the cell template. + +The next step is to define the table's header-row (`cdkHeaderRowDef`) and data-row (`cdkRowDef`). +Each should be provided a list of which columns should be rendered and in which order. ```html ``` +Note that `cdkRowDef` also exports row context, which can be used to apply event and attribute +bindings that use the row data (and additional fields). + In the following template, we have a data table that displays three columns: Column A, Column B, and Column C. The and are given an input of what columns to display. @@ -62,15 +63,15 @@ The and are given an input of what columns to display {{row.c}} - + ``` -It is not required to display all the columns that are defined within the template, -nor is the order required. For example, if we wanted the table to display only Column B -and Column A and in that order, then the template would look like this: +Note that it is not required to display all the columns that are defined within the template, +nor use the same ordering. For example, to display the table with only Column B +and Column A and in that order, then the row and header definitions would be written as: ```html @@ -94,86 +95,21 @@ property is greater than 20. ``` Changing the list of columns provided to the `` and `` will automatically -cause the table to re-render to reflect those changes. For more information, see Dynamic Columns below under Features. +cause the table to re-render to reflect those changes. ### Connecting the table to a data source Data is provided to the table through the `DataSource` interface. When the table receives a DataSource, -it calls its connect function to receive an observable that emits an array of data. Whenever the Data Source emits data to this stream, the table will use it to render its rows. +it calls the DataSource's connect function which returns an observable that emits an array of data. +Whenever the Data Source emits data to this stream, the table will use it to render its rows. Since the Data Source provides this data stream, it is responsible for watching for data changes -and notifying the table when to re-render. Examples of these data changes includes sorting, pagination, filtering, and more. -To see how these examples can be incorporated in the Data Source, see below under Features. +and notifying the table when to re-render. Examples of these data changes includes sorting, pagination, +filtering, and more. -Note that a trackBy function can be provided to the table similar to Angular’s ngFor trackBy. -This allows you to customize how the table to identifies rows and improves performance. +To improve performance, a trackBy function can be provided to the table similar to Angular’s ngFor trackBy. +This allows you to customize how the table to identifies rows and helps it to understand how +the data is changing. In the future, the connect function will be able to use the CollectionViewer parameter to be notified about table events, such as what rows the user is currently viewing. This could be used to -help the Data Source know what data does not need to be retrieved and rendered, further improving performance. - -## Material Table -To use the CDK Data Table with styles matching the Material Design spec, you can use the `` -defined in `@angular/material`. This will build on the CDK Data Table and apply built-in Material Design styles. - -The interface for the `` matches the ``, except that its element selectors -will be prefixed with `md-` instead of `cdk-`. - -Note that the column definition directives (`cdkColumnDef` and `cdkHeaderCellDef`) are still prefixed with `cdk-`. - -```html - - - - Column A - {{row.a}} - - - - - Column B - {{row.b}} - - - - - Column C - {{row.c}} - - - - - - -``` - -## Simple Table - -In the near future, we would like to provide a simple version of the data table that includes an easy-to-use interface, -material styling, data array input, and out-of-the-box features such as sorting, pagination, and selection. - -## Features - -The CDK Table’s responsibility is to handle efficient rendering of rows and it’s the Data Source’s job -to let the table know what data should be rendered. As such, features that manipulate what data should -be rendered should be the responsibility of the data source. - -### Pagination -Use the MdPagination component to add data paging to the data table. The data source can listen to -paging events from the component and appropriately slice the right data from whatever data provider -is used. Sending this new data to the table will cause it to render the new page of data. - - - -### Sorting -Use the MdSort component to enable sorting the table's data through the column headers. -The data source can listen to sorting events from the component and sort the data before giving it -to the table to render. - - - -### Filtering - -Apply filtering to your table's data by listening to an input's changes. -When a change occurs, filter the data in the data source and send it to the table to render. - - \ No newline at end of file +help the Data Source know what data does not need to be retrieved and rendered, further improving performance. \ No newline at end of file diff --git a/src/lib/table/table.md b/src/lib/table/table.md new file mode 100644 index 000000000000..ae35f461f620 --- /dev/null +++ b/src/lib/table/table.md @@ -0,0 +1,43 @@ +The `md-table` provides a Material Design styled data table that can be used to display rows of data. + +This table builds on the foundation of the CDK data-table and uses a similar interface for its +data source input and template, except that its element selectors will be prefixed with `md-` instead of `cdk-`. + + + +Note that the column definition directives (`cdkColumnDef` and `cdkHeaderCellDef`) are still prefixed with `cdk-`. + +For more information on the interface and how it works, see the guide covering the CDK data-table. + +## Simple Table + +In the near future, we would like to provide a simple version of the data table that includes an easy-to-use interface, +material styling, data array input, and out-of-the-box features such as sorting, pagination, and selection. + +## Features + +Adding features on top of the `md-table` such as sorting and pagination can be done by merging +events within the data source and sending the updated data to the table through the stream provided +in the `connect` function. + +### Pagination + +Use the `md-pagination` component to add data paging to the table. The data source can listen to +paging events from the component and appropriately slice the right data from whatever data provider +is used. Sending this new data to the table will cause it to render the new page of data. + + + +### Sorting +Use the `mdSort` directive and `md-sort-header` component to enable sorting on the table through +the column headers. The data source can listen to sorting events from the component and sort the data +before giving it to the table to render. + + + +### Filtering + +Apply filtering to your table's data by listening to an input's changes. +When a change occurs, filter the data in the data source and send it to the table to render. + + \ No newline at end of file diff --git a/src/material-examples/table-basic/table-basic-example.css b/src/material-examples/table-basic/table-basic-example.css index 4da5dfaea774..7c28e7130685 100644 --- a/src/material-examples/table-basic/table-basic-example.css +++ b/src/material-examples/table-basic/table-basic-example.css @@ -15,34 +15,6 @@ font-size: 20px; } -/* - * Styles to make the demo's cdk-table match the material design spec - * https://material.io/guidelines/components/data-tables.html - */ -.cdk-table { - flex: 1 1 auto; +.mat-table { overflow: auto; } - -.cdk-row, .cdk-header-row { - display: flex; - border-bottom: 1px solid #ccc; - align-items: center; - height: 48px; - padding: 0 24px; -} - -.cdk-cell, .cdk-header-cell { - flex: 1; -} - -.cdk-header-cell { - font-size: 12px; - font-weight: bold; - color: rgba(0, 0, 0, 0.54); -} - -.cdk-cell { - font-size: 13px; - color: rgba(0, 0, 0, 0.87); -} \ No newline at end of file diff --git a/src/material-examples/table-basic/table-basic-example.html b/src/material-examples/table-basic/table-basic-example.html index b6d597bef2f4..159f10561346 100644 --- a/src/material-examples/table-basic/table-basic-example.html +++ b/src/material-examples/table-basic/table-basic-example.html @@ -1,37 +1,36 @@
Users
- + - ID - {{row.id}} + ID + {{row.id}} - Progress - {{row.progress}}% + Progress + {{row.progress}}% - Name - {{row.name}} + Name + {{row.name}} - Color - {{row.color}} + Color + {{row.color}} - - - - + + +
\ No newline at end of file diff --git a/src/material-examples/table-filtering/table-filtering-example.css b/src/material-examples/table-filtering/table-filtering-example.css index 08398d06df0a..4c19d12bff8a 100644 --- a/src/material-examples/table-filtering/table-filtering-example.css +++ b/src/material-examples/table-filtering/table-filtering-example.css @@ -30,34 +30,6 @@ margin-left: 32px; } -/* - * Styles to make the demo's cdk-table match the material design spec - * https://material.io/guidelines/components/data-tables.html - */ -.cdk-table { - flex: 1 1 auto; +.mat-table { overflow: auto; } - -.cdk-row, .cdk-header-row { - display: flex; - border-bottom: 1px solid #ccc; - align-items: center; - height: 48px; - padding: 0 24px; -} - -.cdk-cell, .cdk-header-cell { - flex: 1; -} - -.cdk-header-cell { - font-size: 12px; - font-weight: bold; - color: rgba(0, 0, 0, 0.54); -} - -.cdk-cell { - font-size: 13px; - color: rgba(0, 0, 0, 0.87); -} \ No newline at end of file diff --git a/src/material-examples/table-filtering/table-filtering-example.html b/src/material-examples/table-filtering/table-filtering-example.html index cfed5b4a0e73..89018a27d804 100644 --- a/src/material-examples/table-filtering/table-filtering-example.html +++ b/src/material-examples/table-filtering/table-filtering-example.html @@ -7,37 +7,36 @@ - + - ID - {{row.id}} + ID + {{row.id}} - Progress - {{row.progress}}% + Progress + {{row.progress}}% - Name - {{row.name}} + Name + {{row.name}} - Color - {{row.color}} + Color + {{row.color}} - - - - + + +
\ No newline at end of file diff --git a/src/material-examples/table-overview/table-overview-example.css b/src/material-examples/table-overview/table-overview-example.css index f63c79970d5f..45423e074af9 100644 --- a/src/material-examples/table-overview/table-overview-example.css +++ b/src/material-examples/table-overview/table-overview-example.css @@ -40,46 +40,18 @@ border-bottom: 1px solid #d696ac; } -.cdk-column-select { +.mat-column-select { max-width: 54px; } -.cdk-row:hover, .example-selected-row { +.mat-row:hover, .example-selected-row { background: #F5F5F5; } -.cdk-row:active, .cdk-row.example-selected-row { +.mat-row:active, .mat-row.example-selected-row { background: #EAEAEA; } -/* - * Styles to make the demo's cdk-table match the material design spec - * https://material.io/guidelines/components/data-tables.html - */ -.cdk-table { - flex: 1 1 auto; +.mat-table { overflow: auto; } - -.cdk-row, .cdk-header-row { - display: flex; - border-bottom: 1px solid #ccc; - align-items: center; - height: 48px; - padding: 0 24px; -} - -.cdk-cell, .cdk-header-cell { - flex: 1; -} - -.cdk-header-cell { - font-size: 12px; - font-weight: bold; - color: rgba(0, 0, 0, 0.54); -} - -.cdk-cell { - font-size: 13px; - color: rgba(0, 0, 0, 0.87); -} diff --git a/src/material-examples/table-overview/table-overview-example.html b/src/material-examples/table-overview/table-overview-example.html index 7d68f9afb0ab..c274009e6b1a 100644 --- a/src/material-examples/table-overview/table-overview-example.html +++ b/src/material-examples/table-overview/table-overview-example.html @@ -13,57 +13,57 @@ selected - + - + - - + + - + - ID - {{row.id}} + ID + {{row.id}} - Progress - {{row.progress}}% + Progress + {{row.progress}}% - Name - {{row.name}} + Name + {{row.name}} - Color - {{row.color}} + Color + {{row.color}} - - + - - + +
diff --git a/src/material-examples/table-pagination/table-pagination-example.css b/src/material-examples/table-pagination/table-pagination-example.css index 4da5dfaea774..7c28e7130685 100644 --- a/src/material-examples/table-pagination/table-pagination-example.css +++ b/src/material-examples/table-pagination/table-pagination-example.css @@ -15,34 +15,6 @@ font-size: 20px; } -/* - * Styles to make the demo's cdk-table match the material design spec - * https://material.io/guidelines/components/data-tables.html - */ -.cdk-table { - flex: 1 1 auto; +.mat-table { overflow: auto; } - -.cdk-row, .cdk-header-row { - display: flex; - border-bottom: 1px solid #ccc; - align-items: center; - height: 48px; - padding: 0 24px; -} - -.cdk-cell, .cdk-header-cell { - flex: 1; -} - -.cdk-header-cell { - font-size: 12px; - font-weight: bold; - color: rgba(0, 0, 0, 0.54); -} - -.cdk-cell { - font-size: 13px; - color: rgba(0, 0, 0, 0.87); -} \ No newline at end of file diff --git a/src/material-examples/table-pagination/table-pagination-example.html b/src/material-examples/table-pagination/table-pagination-example.html index e32a83efb3a5..d6c72ad51e78 100644 --- a/src/material-examples/table-pagination/table-pagination-example.html +++ b/src/material-examples/table-pagination/table-pagination-example.html @@ -1,39 +1,38 @@
Users
- + - ID - {{row.id}} + ID + {{row.id}} - Progress - {{row.progress}}% + Progress + {{row.progress}}% - Name - {{row.name}} + Name + {{row.name}} - Color - {{row.color}} + Color + {{row.color}} - - - - + + +
Users
- + - ID - {{row.id}} + ID + {{row.id}} - Progress - {{row.progress}}% + Progress + {{row.progress}}% - Name - {{row.name}} + Name + {{row.name}} - Color - {{row.color}} + Color + {{row.color}} - - - - + + +
\ No newline at end of file From 9ce5c0ae1e55a554a45d7f8fee2d0b1a414eccac Mon Sep 17 00:00:00 2001 From: Andrew Seguin Date: Wed, 5 Jul 2017 14:57:26 -0700 Subject: [PATCH 06/12] revisions --- src/cdk/table/table.md | 139 ++++++++++-------- src/lib/table/table.md | 48 +++--- .../cdk-table-basic-example.css | 47 ++++++ .../cdk-table-basic-example.html | 36 +++++ .../ckd-table-basic-example.ts | 89 +++++++++++ src/material-examples/example-module.ts | 3 + 6 files changed, 278 insertions(+), 84 deletions(-) create mode 100644 src/material-examples/cdk-table-basic/cdk-table-basic-example.css create mode 100644 src/material-examples/cdk-table-basic/cdk-table-basic-example.html create mode 100644 src/material-examples/cdk-table-basic/ckd-table-basic-example.ts diff --git a/src/cdk/table/table.md b/src/cdk/table/table.md index 1c985d385e8b..035c43f10c8c 100644 --- a/src/cdk/table/table.md +++ b/src/cdk/table/table.md @@ -1,115 +1,128 @@ -The CDK data-table displays rows of data with fully customizable cell templates. -Its single responsibility is the efficient rendering of rows in a fully accessible way. +The `` is an unopinionated, customizable data-table with a fully-templated API, dynamic +columns, and an accessible DOM structure. This component acts as the core upon which anyone can +build their own tailored data-table experience. -The table provides a foundation upon which other features, such as sorting and pagination, can be built. -Because it enforces no opinions on these matters, developers have full control over the interaction patterns associated with the table. +The table provides a foundation upon which other features, such as sorting and pagination, can be +built. Because it enforces no opinions on these matters, developers have full control over the +interaction patterns associated with the table. -For a Material Design styled table, see the documentation for `` which builds on top of the CDK data-table. +For a Material Design styled table, see the documentation for `` which builds on top of +the CDK data-table. -In the near future, the material library will include an additional "simple table", -building `` with a more minimal interface and sorting, pagination, and selection built-in. + -## Using the CDK Data Table +### Using the CDK data-table -### Writing your table template +#### Writing your table template The first step to writing the data-table template is to define the columns. A column definition is specified via an `` with the `cdkColumnDef` directive, giving -column a name. Each column definition then contains further definitions for both a header-cell -template (`cdkHeaderCellDef`) and a data-cell template (`cdkCellDef`). +column a name. Each column definition then further defines both a header-cell template +(`cdkHeaderCellDef`) and a data-cell template (`cdkCellDef`). ```html - - Column A + + User name {{row.a}} ``` -Note that `cdkCellDef` exports the row context such that the row data (and additional fields) can -be referenced in the cell template. +The set of columns defined represent the columns that are _available_ to be rendered. The specific +columns rendered in a given row, and their order, are specified on the row (see below). + +Note that `cdkCellDef` exports the row context such that the row data can be referenced in the cell +template. The directive also exports the same properties as `ngFor` (index, even, odd, first, +last). The next step is to define the table's header-row (`cdkHeaderRowDef`) and data-row (`cdkRowDef`). -Each should be provided a list of which columns should be rendered and in which order. ```html - - + + ``` -Note that `cdkRowDef` also exports row context, which can be used to apply event and attribute -bindings that use the row data (and additional fields). +These row templates accept the specific columns to be rendered via the name given to the +`cdkColumnDef`. + + +The `cdkRowDef` also exports row context, which can be used for event and property +bindings on the row element. Any content placed _inside_ of the header row or data row template +will be ignored, as the rendered content of the row comes from the cell templates described +above. -In the following template, we have a data table that displays three columns: Column A, Column B, and Column C. -The and are given an input of what columns to display. +##### Example: table with three columns ```html - - - Column A - {{row.a}} + + + User name + {{row.username}} - - - Column B - {{row.b}} + + + Age + {{row.age}} - - - Column C - {{row.c}} + + + Title + {{row.title}} - - + + ``` -Note that it is not required to display all the columns that are defined within the template, -nor use the same ordering. For example, to display the table with only Column B -and Column A and in that order, then the row and header definitions would be written as: +The columns given on the row determine which cells are rendered and in which order. Thus, the +columns can be set via binding to support dynamically changing the columns shown at run-time. + + +It is not required to display all the columns that are defined within the template, +nor use the same ordering. For example, to display the table with only `age` +and `username` and in that order, then the row and header definitions would be written as: ```html - - + ``` -Adding attribute and event binding to the header and rows is as simple as applying them to the -`` and ``. For example, here the table is adding a click handler to both. -In addition, the CSS class `a-bigger-than-twenty` will be applied to any row where its data’s `a` -property is greater than 20. +Event and property bindings can be added directly to the row element. +##### Example: table with event and class binding ```html - - 20” + = 18” (click)=”handleRowClick(row)”> ``` -Changing the list of columns provided to the `` and `` will automatically -cause the table to re-render to reflect those changes. - -### Connecting the table to a data source -Data is provided to the table through the `DataSource` interface. When the table receives a DataSource, +#### Connecting the table to a data source +Data is provided to the table through a `DataSource`. When the table receives a data source, it calls the DataSource's connect function which returns an observable that emits an array of data. -Whenever the Data Source emits data to this stream, the table will use it to render its rows. +Whenever the data source emits data to this stream, the table will update. + +Because the _data source_ provides this stream, it bears the responsibility of triggering table +updates. This can be based on _anything_: websocket connections, user interaction, model updates, +time-based intervals, etc. Most commonly, updates will be triggered by user interactions like +sorting and pagination. + +##### `trackBy` +To improve performance, a trackBy function can be provided to the table similar to Angular’s +(`ngFor` trackBy)[trackBy]. This informs the table how to uniquely identify rows to track how the +data changes with each update. -Since the Data Source provides this data stream, it is responsible for watching for data changes -and notifying the table when to re-render. Examples of these data changes includes sorting, pagination, -filtering, and more. +```html + +``` -To improve performance, a trackBy function can be provided to the table similar to Angular’s ngFor trackBy. -This allows you to customize how the table to identifies rows and helps it to understand how -the data is changing. -In the future, the connect function will be able to use the CollectionViewer parameter to be -notified about table events, such as what rows the user is currently viewing. This could be used to -help the Data Source know what data does not need to be retrieved and rendered, further improving performance. \ No newline at end of file +[trackBy][https://angular.io/api/common/NgForOf#change-propagation] \ No newline at end of file diff --git a/src/lib/table/table.md b/src/lib/table/table.md index ae35f461f620..a25badd50a64 100644 --- a/src/lib/table/table.md +++ b/src/lib/table/table.md @@ -1,43 +1,49 @@ -The `md-table` provides a Material Design styled data table that can be used to display rows of data. +The `md-table` provides a Material Design styled data-table that can be used to display rows of +data. This table builds on the foundation of the CDK data-table and uses a similar interface for its -data source input and template, except that its element selectors will be prefixed with `md-` instead of `cdk-`. - +data source input and template, except that its element selectors will be prefixed with `md-` +instead of `cdk-`. + -Note that the column definition directives (`cdkColumnDef` and `cdkHeaderCellDef`) are still prefixed with `cdk-`. +Note that the column definition directives (`cdkColumnDef` and `cdkHeaderCellDef`) are still +prefixed with `cdk-`. For more information on the interface and how it works, see the guide covering the CDK data-table. -## Simple Table - -In the near future, we would like to provide a simple version of the data table that includes an easy-to-use interface, -material styling, data array input, and out-of-the-box features such as sorting, pagination, and selection. - ## Features -Adding features on top of the `md-table` such as sorting and pagination can be done by merging -events within the data source and sending the updated data to the table through the stream provided -in the `connect` function. +The `` itself only deals with the rendering of a table structure (rows and cells). +Additional features can be built on top of the table by adding behavior inside cell templates +(e.g., sort headers) or next to the table (e.g. a paginator). Interactions that affect the +rendered data (such as sorting and pagination) should be propagated through the table's data source. + ### Pagination -Use the `md-pagination` component to add data paging to the table. The data source can listen to -paging events from the component and appropriately slice the right data from whatever data provider -is used. Sending this new data to the table will cause it to render the new page of data. +The `` adds a pagination UI that can be used in conjunction with the ``. The +paginator emits events that can be used to trigger an update via the table's data source. ### Sorting -Use the `mdSort` directive and `md-sort-header` component to enable sorting on the table through -the column headers. The data source can listen to sorting events from the component and sort the data -before giving it to the table to render. +Use the `mdSort` directive and `` adds a sorting UI the table's column headers. The +sort headers emit events that can be used to trigger an update via the table's data source. ### Filtering -Apply filtering to your table's data by listening to an input's changes. -When a change occurs, filter the data in the data source and send it to the table to render. +While Angular Material does not offer a specific component for filtering tabular data, the table's +data source can be updated based on any custom filter UI. Any filtering pattern need only trigger +an update via the table's data source. + + + + +## Simple Table - \ No newline at end of file +In the near future, we will provide a simplified version of the data-table with an easy-to-use +interface, material styling, array input, and more out-of-the-box features (sorting, pagination, +and selection). \ No newline at end of file diff --git a/src/material-examples/cdk-table-basic/cdk-table-basic-example.css b/src/material-examples/cdk-table-basic/cdk-table-basic-example.css new file mode 100644 index 000000000000..390e97af761b --- /dev/null +++ b/src/material-examples/cdk-table-basic/cdk-table-basic-example.css @@ -0,0 +1,47 @@ +/* Structure */ +.example-container { + display: flex; + flex-direction: column; + max-height: 500px; + min-width: 300px; +} + +.example-header { + min-height: 64px; + display: flex; + align-items: center; + padding-left: 24px; + font-size: 20px; +} + +/* + * Styles to make the demo's cdk-table match the material design spec + * https://material.io/guidelines/components/data-tables.html + */ +.cdk-table { + flex: 1 1 auto; + overflow: auto; +} + +.cdk-row, .cdk-header-row { + display: flex; + border-bottom: 1px solid #ccc; + align-items: center; + height: 32px; + padding: 0 8px; +} + +.cdk-cell, .cdk-header-cell { + flex: 1; +} + +.cdk-header-cell { + font-size: 12px; + font-weight: bold; + color: rgba(0, 0, 0, 0.54); +} + +.cdk-cell { + font-size: 13px; + color: rgba(0, 0, 0, 0.87); +} \ No newline at end of file diff --git a/src/material-examples/cdk-table-basic/cdk-table-basic-example.html b/src/material-examples/cdk-table-basic/cdk-table-basic-example.html new file mode 100644 index 000000000000..d6309c051d9b --- /dev/null +++ b/src/material-examples/cdk-table-basic/cdk-table-basic-example.html @@ -0,0 +1,36 @@ +
+
Users
+ + + + + + + + ID + {{row.id}} + + + + + Progress + {{row.progress}}% + + + + + Name + {{row.name}} + + + + + Color + {{row.color}} + + + + + +
\ No newline at end of file diff --git a/src/material-examples/cdk-table-basic/ckd-table-basic-example.ts b/src/material-examples/cdk-table-basic/ckd-table-basic-example.ts new file mode 100644 index 000000000000..f9b183f9e348 --- /dev/null +++ b/src/material-examples/cdk-table-basic/ckd-table-basic-example.ts @@ -0,0 +1,89 @@ +import {Component} from '@angular/core'; +import {DataSource} from '@angular/cdk'; +import {BehaviorSubject} from 'rxjs/BehaviorSubject'; +import {Observable} from 'rxjs/Observable'; +import 'rxjs/add/operator/startWith'; +import 'rxjs/add/observable/merge'; +import 'rxjs/add/operator/map'; + +@Component({ + selector: 'cdk-table-basic-example', + styleUrls: ['cdk-table-basic-example.css'], + templateUrl: 'cdk-table-basic-example.html', +}) +export class CdkTableBasicExample { + displayedColumns = ['userId', 'userName', 'progress', 'color']; + exampleDatabase = new ExampleDatabase(); + dataSource: ExampleDataSource | null; + + ngOnInit() { + this.dataSource = new ExampleDataSource(this.exampleDatabase); + } +} + +/** Constants used to fill up our data base. */ +const COLORS = ['maroon', 'red', 'orange', 'yellow', 'olive', 'green', 'purple', + 'fuchsia', 'lime', 'teal', 'aqua', 'blue', 'navy', 'black', 'gray']; +const NAMES = ['Maia', 'Asher', 'Olivia', 'Atticus', 'Amelia', 'Jack', + 'Charlotte', 'Theodore', 'Isla', 'Oliver', 'Isabella', 'Jasper', + 'Cora', 'Levi', 'Violet', 'Arthur', 'Mia', 'Thomas', 'Elizabeth']; + +export interface UserData { + id: string; + name: string; + progress: string; + color: string; +} + +/** An example database that the data source uses to retrieve data for the table. */ +export class ExampleDatabase { + /** Stream that emits whenever the data has been modified. */ + dataChange: BehaviorSubject = new BehaviorSubject([]); + get data(): UserData[] { return this.dataChange.value; } + + constructor() { + // Fill up the database with 100 users. + for (let i = 0; i < 100; i++) { this.addUser(); } + } + + /** Adds a new user to the database. */ + addUser() { + const copiedData = this.data.slice(); + copiedData.push(this.createNewUser()); + this.dataChange.next(copiedData); + } + + /** Builds and returns a new User. */ + private createNewUser() { + const name = + NAMES[Math.round(Math.random() * (NAMES.length - 1))] + ' ' + + NAMES[Math.round(Math.random() * (NAMES.length - 1))].charAt(0) + '.'; + + return { + id: (this.data.length + 1).toString(), + name: name, + progress: Math.round(Math.random() * 100).toString(), + color: COLORS[Math.round(Math.random() * (COLORS.length - 1))] + }; + } +} + +/** + * Data source to provide what data should be rendered in the table. Note that the data source + * can retrieve its data in any way. In this case, the data source is provided a reference + * to a common data base, ExampleDatabase. It is not the data source's responsibility to manage + * the underlying data. Instead, it only needs to take the data and send the table exactly what + * should be rendered. + */ +export class ExampleDataSource extends DataSource { + constructor(private _exampleDatabase: ExampleDatabase) { + super(); + } + + /** Connect function called by the table to retrieve one stream containing the data to render. */ + connect(): Observable { + return this._exampleDatabase.dataChange; + } + + disconnect() {} +} diff --git a/src/material-examples/example-module.ts b/src/material-examples/example-module.ts index 8d2eb6dddfac..6523fcbf28a9 100644 --- a/src/material-examples/example-module.ts +++ b/src/material-examples/example-module.ts @@ -97,6 +97,7 @@ import {TablePaginationExample} from './table-pagination/table-pagination-exampl import {TableBasicExample} from './table-basic/table-basic-example'; import {TableSortingExample} from './table-sorting/table-sorting-example'; import {TableFilteringExample} from './table-filtering/table-filtering-example'; +import {CdkTableBasicExample} from './cdk-table-basic/ckd-table-basic-example'; export interface LiveExample { title: string; @@ -120,6 +121,7 @@ export const EXAMPLE_COMPONENTS = { }, 'button-toggle-overview': {title: 'Basic button-toggles', component: ButtonToggleOverviewExample}, 'chips-overview': {title: 'Basic chips', component: ChipsOverviewExample}, + 'cdk-table-basic': {title: 'Basic CDK data-table', component: CdkTableBasicExample} 'chips-stacked': {title: 'Stacked chips', component: ChipsStackedExample}, 'card-fancy': {title: 'Card with multiple sections', component: CardFancyExample}, 'card-overview': {title: 'Basic cards', component: CardOverviewExample}, @@ -261,6 +263,7 @@ export const EXAMPLE_LIST = [ ButtonTypesExample, CardFancyExample, CardOverviewExample, + CdkTableBasicExample, ChipsOverviewExample, ChipsStackedExample, CheckboxConfigurableExample, From a581204863ae6b100eedf7cd14d4419b7bfa408a Mon Sep 17 00:00:00 2001 From: Andrew Seguin Date: Wed, 5 Jul 2017 15:04:29 -0700 Subject: [PATCH 07/12] add to examples --- src/cdk/table/table.md => guides/cdk-table.md | 0 src/material-examples/example-module.ts | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/cdk/table/table.md => guides/cdk-table.md (100%) diff --git a/src/cdk/table/table.md b/guides/cdk-table.md similarity index 100% rename from src/cdk/table/table.md rename to guides/cdk-table.md diff --git a/src/material-examples/example-module.ts b/src/material-examples/example-module.ts index 6523fcbf28a9..226f2574bd36 100644 --- a/src/material-examples/example-module.ts +++ b/src/material-examples/example-module.ts @@ -121,7 +121,7 @@ export const EXAMPLE_COMPONENTS = { }, 'button-toggle-overview': {title: 'Basic button-toggles', component: ButtonToggleOverviewExample}, 'chips-overview': {title: 'Basic chips', component: ChipsOverviewExample}, - 'cdk-table-basic': {title: 'Basic CDK data-table', component: CdkTableBasicExample} + 'cdk-table-basic': {title: 'Basic CDK data-table', component: CdkTableBasicExample}, 'chips-stacked': {title: 'Stacked chips', component: ChipsStackedExample}, 'card-fancy': {title: 'Card with multiple sections', component: CardFancyExample}, 'card-overview': {title: 'Basic cards', component: CardOverviewExample}, From 453d1cbe0a001b0e77354ca407187c72c472ee34 Mon Sep 17 00:00:00 2001 From: Andrew Seguin Date: Wed, 5 Jul 2017 15:19:26 -0700 Subject: [PATCH 08/12] fix heading --- src/lib/table/table.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lib/table/table.md b/src/lib/table/table.md index a25badd50a64..e70f8fbfc146 100644 --- a/src/lib/table/table.md +++ b/src/lib/table/table.md @@ -12,7 +12,7 @@ prefixed with `cdk-`. For more information on the interface and how it works, see the guide covering the CDK data-table. -## Features +### Features The `` itself only deals with the rendering of a table structure (rows and cells). Additional features can be built on top of the table by adding behavior inside cell templates @@ -20,20 +20,20 @@ Additional features can be built on top of the table by adding behavior inside c rendered data (such as sorting and pagination) should be propagated through the table's data source. -### Pagination +#### Pagination The `` adds a pagination UI that can be used in conjunction with the ``. The paginator emits events that can be used to trigger an update via the table's data source. -### Sorting +#### Sorting Use the `mdSort` directive and `` adds a sorting UI the table's column headers. The sort headers emit events that can be used to trigger an update via the table's data source. -### Filtering +#### Filtering While Angular Material does not offer a specific component for filtering tabular data, the table's data source can be updated based on any custom filter UI. Any filtering pattern need only trigger @@ -42,7 +42,7 @@ an update via the table's data source. -## Simple Table +### Simple Table In the near future, we will provide a simplified version of the data-table with an easy-to-use interface, material styling, array input, and more out-of-the-box features (sorting, pagination, From bc32022322bcabe31941d114e8a7bf19ca24209b Mon Sep 17 00:00:00 2001 From: Andrew Seguin Date: Wed, 5 Jul 2017 15:49:46 -0700 Subject: [PATCH 09/12] example changes --- .../cdk-table-basic/cdk-table-basic-example.css | 8 -------- .../cdk-table-basic/cdk-table-basic-example.html | 3 --- src/material-examples/example-module.ts | 3 ++- .../table-overview/table-overview-example.html | 2 +- .../table-overview/table-overview-example.ts | 5 +++-- 5 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/material-examples/cdk-table-basic/cdk-table-basic-example.css b/src/material-examples/cdk-table-basic/cdk-table-basic-example.css index 390e97af761b..698d9f38ea4e 100644 --- a/src/material-examples/cdk-table-basic/cdk-table-basic-example.css +++ b/src/material-examples/cdk-table-basic/cdk-table-basic-example.css @@ -6,14 +6,6 @@ min-width: 300px; } -.example-header { - min-height: 64px; - display: flex; - align-items: center; - padding-left: 24px; - font-size: 20px; -} - /* * Styles to make the demo's cdk-table match the material design spec * https://material.io/guidelines/components/data-tables.html diff --git a/src/material-examples/cdk-table-basic/cdk-table-basic-example.html b/src/material-examples/cdk-table-basic/cdk-table-basic-example.html index d6309c051d9b..173c05a14c07 100644 --- a/src/material-examples/cdk-table-basic/cdk-table-basic-example.html +++ b/src/material-examples/cdk-table-basic/cdk-table-basic-example.html @@ -1,8 +1,5 @@
-
Users
- - diff --git a/src/material-examples/example-module.ts b/src/material-examples/example-module.ts index 226f2574bd36..c12f99ed9a7e 100644 --- a/src/material-examples/example-module.ts +++ b/src/material-examples/example-module.ts @@ -89,7 +89,7 @@ import { MdChipsModule, MdDatepickerModule, MdDialogModule, MdGridListModule, MdIconModule, MdInputModule, MdListModule, MdMenuModule, MdPaginatorModule, MdProgressBarModule, MdProgressSpinnerModule, MdRadioModule, MdSelectModule, MdSidenavModule, MdSliderModule, MdSlideToggleModule, - MdSnackBarModule, MdSortModule, MdTabsModule, MdToolbarModule, MdTooltipModule + MdSnackBarModule, MdSortModule, MdTableModule, MdTabsModule, MdToolbarModule, MdTooltipModule } from '@angular/material'; import {CdkTableModule} from '@angular/cdk'; import {TableOverviewExample} from './table-overview/table-overview-example'; @@ -244,6 +244,7 @@ export const EXAMPLE_COMPONENTS = { MdSliderModule, MdSidenavModule, MdSnackBarModule, + MdTableModule, MdTabsModule, MdToolbarModule, MdTooltipModule diff --git a/src/material-examples/table-overview/table-overview-example.html b/src/material-examples/table-overview/table-overview-example.html index c274009e6b1a..eeac9604837b 100644 --- a/src/material-examples/table-overview/table-overview-example.html +++ b/src/material-examples/table-overview/table-overview-example.html @@ -71,7 +71,7 @@
diff --git a/src/material-examples/table-overview/table-overview-example.ts b/src/material-examples/table-overview/table-overview-example.ts index 37725ef42c2b..568aebc5f255 100644 --- a/src/material-examples/table-overview/table-overview-example.ts +++ b/src/material-examples/table-overview/table-overview-example.ts @@ -119,6 +119,7 @@ export class ExampleDataSource extends DataSource { get filter(): string { return this._filterChange.value; } set filter(filter: string) { this._filterChange.next(filter); } + filteredData: UserData[] = []; renderedData: UserData[] = []; constructor(private _exampleDatabase: ExampleDatabase, @@ -139,13 +140,13 @@ export class ExampleDataSource extends DataSource { return Observable.merge(...displayDataChanges).map(() => { // Filter data - const filteredData = this._exampleDatabase.data.slice().filter((item: UserData) => { + this.filteredData = this._exampleDatabase.data.slice().filter((item: UserData) => { let searchStr = (item.name + item.color).toLowerCase(); return searchStr.indexOf(this.filter.toLowerCase()) != -1; }); // Sort filtered data - const sortedData = this.sortData(filteredData); + const sortedData = this.sortData(this.filteredData.slice()); // Grab the page's slice of the filtered sorted data. const startIndex = this._paginator.pageIndex * this._paginator.pageSize; From de89a081b5677fd00fcd804fcea46824533c6a81 Mon Sep 17 00:00:00 2001 From: Andrew Seguin Date: Wed, 5 Jul 2017 15:52:16 -0700 Subject: [PATCH 10/12] lint --- .../table-filtering/table-filtering-example.css | 2 +- .../table-filtering/table-filtering-example.ts | 5 ----- .../table-overview/table-overview-example.css | 8 ++++---- 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/material-examples/table-filtering/table-filtering-example.css b/src/material-examples/table-filtering/table-filtering-example.css index 4c19d12bff8a..806488d90fb1 100644 --- a/src/material-examples/table-filtering/table-filtering-example.css +++ b/src/material-examples/table-filtering/table-filtering-example.css @@ -19,7 +19,7 @@ min-height: 64px; display: flex; align-items: baseline; - padding: 8px 24px 0 24px; + padding: 8px 24px 0; font-size: 20px; justify-content: space-between; } diff --git a/src/material-examples/table-filtering/table-filtering-example.ts b/src/material-examples/table-filtering/table-filtering-example.ts index 8210e4a32027..ad5226f4fbbc 100644 --- a/src/material-examples/table-filtering/table-filtering-example.ts +++ b/src/material-examples/table-filtering/table-filtering-example.ts @@ -114,8 +114,3 @@ export class ExampleDataSource extends DataSource { disconnect() {} } - - -/** Copyright 2017 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 http://angular.io/license */ \ No newline at end of file diff --git a/src/material-examples/table-overview/table-overview-example.css b/src/material-examples/table-overview/table-overview-example.css index 45423e074af9..3e9ead915745 100644 --- a/src/material-examples/table-overview/table-overview-example.css +++ b/src/material-examples/table-overview/table-overview-example.css @@ -12,7 +12,7 @@ max-height: 56px; display: flex; align-items: center; - padding: 8px 24px 0 24px; + padding: 8px 24px 0; font-size: 20px; justify-content: space-between; border-bottom: 1px solid transparent; @@ -36,7 +36,7 @@ /** Selection styles */ .example-selection-header { font-size: 18px; - background: rgba(255, 64, 129, .3); + background: rgba(255, 64, 129, 0.3); border-bottom: 1px solid #d696ac; } @@ -45,11 +45,11 @@ } .mat-row:hover, .example-selected-row { - background: #F5F5F5; + background: #f5f5f5; } .mat-row:active, .mat-row.example-selected-row { - background: #EAEAEA; + background: #eaeaea; } .mat-table { From f027aab842d65fe37ca2fa470a4160470fa1757f Mon Sep 17 00:00:00 2001 From: Andrew Seguin Date: Wed, 5 Jul 2017 16:22:21 -0700 Subject: [PATCH 11/12] example style prefix, rename file --- .../cdk-table-basic-example.css | 10 ++++---- .../cdk-table-basic-example.html | 25 +++++++++++-------- ...-example.ts => cdk-table-basic-example.ts} | 0 src/material-examples/example-module.ts | 2 +- 4 files changed, 20 insertions(+), 17 deletions(-) rename src/material-examples/cdk-table-basic/{ckd-table-basic-example.ts => cdk-table-basic-example.ts} (100%) diff --git a/src/material-examples/cdk-table-basic/cdk-table-basic-example.css b/src/material-examples/cdk-table-basic/cdk-table-basic-example.css index 698d9f38ea4e..8587b7cd402b 100644 --- a/src/material-examples/cdk-table-basic/cdk-table-basic-example.css +++ b/src/material-examples/cdk-table-basic/cdk-table-basic-example.css @@ -10,12 +10,12 @@ * Styles to make the demo's cdk-table match the material design spec * https://material.io/guidelines/components/data-tables.html */ -.cdk-table { +.example-table { flex: 1 1 auto; overflow: auto; } -.cdk-row, .cdk-header-row { +.example-header-row, .example-row { display: flex; border-bottom: 1px solid #ccc; align-items: center; @@ -23,17 +23,17 @@ padding: 0 8px; } -.cdk-cell, .cdk-header-cell { +.example-cell, .example-header-cell { flex: 1; } -.cdk-header-cell { +.example-header-cell { font-size: 12px; font-weight: bold; color: rgba(0, 0, 0, 0.54); } -.cdk-cell { +.example-cell { font-size: 13px; color: rgba(0, 0, 0, 0.87); } \ No newline at end of file diff --git a/src/material-examples/cdk-table-basic/cdk-table-basic-example.html b/src/material-examples/cdk-table-basic/cdk-table-basic-example.html index 173c05a14c07..ff7152a6e362 100644 --- a/src/material-examples/cdk-table-basic/cdk-table-basic-example.html +++ b/src/material-examples/cdk-table-basic/cdk-table-basic-example.html @@ -1,33 +1,36 @@
- + - ID - {{row.id}} + ID + {{row.id}} - Progress - {{row.progress}}% + Progress + {{row.progress}}% - Name - {{row.name}} + Name + {{row.name}} - Color - {{row.color}} + Color + + {{row.color}} + - - + +
\ No newline at end of file diff --git a/src/material-examples/cdk-table-basic/ckd-table-basic-example.ts b/src/material-examples/cdk-table-basic/cdk-table-basic-example.ts similarity index 100% rename from src/material-examples/cdk-table-basic/ckd-table-basic-example.ts rename to src/material-examples/cdk-table-basic/cdk-table-basic-example.ts diff --git a/src/material-examples/example-module.ts b/src/material-examples/example-module.ts index c12f99ed9a7e..460d2950ad94 100644 --- a/src/material-examples/example-module.ts +++ b/src/material-examples/example-module.ts @@ -97,7 +97,7 @@ import {TablePaginationExample} from './table-pagination/table-pagination-exampl import {TableBasicExample} from './table-basic/table-basic-example'; import {TableSortingExample} from './table-sorting/table-sorting-example'; import {TableFilteringExample} from './table-filtering/table-filtering-example'; -import {CdkTableBasicExample} from './cdk-table-basic/ckd-table-basic-example'; +import {CdkTableBasicExample} from './cdk-table-basic/cdk-table-basic-example'; export interface LiveExample { title: string; From 2144b13f4cfb6e9598cac172e4c4734cc86c03c7 Mon Sep 17 00:00:00 2001 From: Andrew Seguin Date: Wed, 5 Jul 2017 16:22:56 -0700 Subject: [PATCH 12/12] newline --- .../cdk-table-basic/cdk-table-basic-example.css | 2 +- .../cdk-table-basic/cdk-table-basic-example.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/material-examples/cdk-table-basic/cdk-table-basic-example.css b/src/material-examples/cdk-table-basic/cdk-table-basic-example.css index 8587b7cd402b..73b5c9b4a454 100644 --- a/src/material-examples/cdk-table-basic/cdk-table-basic-example.css +++ b/src/material-examples/cdk-table-basic/cdk-table-basic-example.css @@ -36,4 +36,4 @@ .example-cell { font-size: 13px; color: rgba(0, 0, 0, 0.87); -} \ No newline at end of file +} diff --git a/src/material-examples/cdk-table-basic/cdk-table-basic-example.html b/src/material-examples/cdk-table-basic/cdk-table-basic-example.html index ff7152a6e362..df20a4d1ed68 100644 --- a/src/material-examples/cdk-table-basic/cdk-table-basic-example.html +++ b/src/material-examples/cdk-table-basic/cdk-table-basic-example.html @@ -33,4 +33,4 @@
-
\ No newline at end of file +