diff --git a/src/material-examples/table-basic/table-basic-example.ts b/src/material-examples/table-basic/table-basic-example.ts index 41f41c7eacb3..c0c243c1d063 100644 --- a/src/material-examples/table-basic/table-basic-example.ts +++ b/src/material-examples/table-basic/table-basic-example.ts @@ -1,7 +1,5 @@ import {Component} from '@angular/core'; -import {DataSource} from '@angular/cdk/collections'; -import {Observable} from 'rxjs/Observable'; -import 'rxjs/add/observable/of'; +import {MatTableDataSource} from '@angular/material'; /** * @title Basic table @@ -13,7 +11,7 @@ import 'rxjs/add/observable/of'; }) export class TableBasicExample { displayedColumns = ['position', 'name', 'weight', 'symbol']; - dataSource = new ExampleDataSource(); + dataSource = new MatTableDataSource(ELEMENT_DATA); } export interface Element { @@ -23,7 +21,7 @@ export interface Element { symbol: string; } -const data: Element[] = [ +const ELEMENT_DATA: Element[] = [ {position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'}, {position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'}, {position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'}, @@ -45,18 +43,3 @@ const data: Element[] = [ {position: 19, name: 'Potassium', weight: 39.0983, symbol: 'K'}, {position: 20, name: 'Calcium', weight: 40.078, symbol: 'Ca'}, ]; - -/** - * Data source to provide what data should be rendered in the table. The observable provided - * in connect should emit exactly the data that should be rendered by the table. If the data is - * altered, the observable should emit that new set of data on the stream. In our case here, - * we return a stream that contains only one set of data that doesn't change. - */ -export class ExampleDataSource extends DataSource { - /** Connect function called by the table to retrieve one stream containing the data to render. */ - connect(): Observable { - return Observable.of(data); - } - - disconnect() {} -} diff --git a/src/material-examples/table-filtering/table-filtering-example.css b/src/material-examples/table-filtering/table-filtering-example.css index 51287a0891d6..c0e9a5b54246 100644 --- a/src/material-examples/table-filtering/table-filtering-example.css +++ b/src/material-examples/table-filtering/table-filtering-example.css @@ -7,17 +7,12 @@ .example-header { min-height: 64px; - display: flex; - align-items: baseline; padding: 8px 24px 0; - font-size: 20px; - justify-content: space-between; } .mat-form-field { font-size: 14px; - flex-grow: 1; - margin-left: 32px; + width: 100%; } .mat-table { diff --git a/src/material-examples/table-filtering/table-filtering-example.html b/src/material-examples/table-filtering/table-filtering-example.html index 0f1f6189d7c9..d9e3e8b46fb2 100644 --- a/src/material-examples/table-filtering/table-filtering-example.html +++ b/src/material-examples/table-filtering/table-filtering-example.html @@ -1,37 +1,34 @@
- - + +
- - - - - ID - {{row.id}} - - - - - Progress - {{row.progress}}% + + + No. + {{element.position}} - + Name - {{row.name}} + {{element.name}} + + + + + Weight + {{element.weight}} - - Color - {{row.color}} + + Symbol + {{element.symbol}} diff --git a/src/material-examples/table-filtering/table-filtering-example.ts b/src/material-examples/table-filtering/table-filtering-example.ts index 8404f0c1b988..3e9ccbb26fcd 100644 --- a/src/material-examples/table-filtering/table-filtering-example.ts +++ b/src/material-examples/table-filtering/table-filtering-example.ts @@ -1,13 +1,5 @@ -import {Component, ElementRef, ViewChild} from '@angular/core'; -import {DataSource} from '@angular/cdk/collections'; -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'; +import {Component} from '@angular/core'; +import {MatTableDataSource} from '@angular/material'; /** * @title Table with filtering @@ -18,101 +10,42 @@ import 'rxjs/add/observable/fromEvent'; templateUrl: 'table-filtering-example.html', }) export class TableFilteringExample { - displayedColumns = ['userId', 'userName', 'progress', 'color']; - exampleDatabase = new ExampleDatabase(); - dataSource: ExampleDataSource | null; + displayedColumns = ['position', 'name', 'weight', 'symbol']; + dataSource = new MatTableDataSource(ELEMENT_DATA); - @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; - }); + applyFilter(filterValue: string) { + filterValue = filterValue.trim(); // Remove whitespace + filterValue = filterValue.toLowerCase(); // MatTableDataSource defaults to lowercase matches + this.dataSource.filter = filterValue; } } -/** 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; +export interface Element { 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))] - }; - } + position: number; + weight: number; + symbol: string; } -/** - * 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() {} -} +const ELEMENT_DATA: Element[] = [ + {position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'}, + {position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'}, + {position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'}, + {position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'}, + {position: 5, name: 'Boron', weight: 10.811, symbol: 'B'}, + {position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'}, + {position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'}, + {position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'}, + {position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'}, + {position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'}, + {position: 11, name: 'Sodium', weight: 22.9897, symbol: 'Na'}, + {position: 12, name: 'Magnesium', weight: 24.305, symbol: 'Mg'}, + {position: 13, name: 'Aluminum', weight: 26.9815, symbol: 'Al'}, + {position: 14, name: 'Silicon', weight: 28.0855, symbol: 'Si'}, + {position: 15, name: 'Phosphorus', weight: 30.9738, symbol: 'P'}, + {position: 16, name: 'Sulfur', weight: 32.065, symbol: 'S'}, + {position: 17, name: 'Chlorine', weight: 35.453, symbol: 'Cl'}, + {position: 18, name: 'Argon', weight: 39.948, symbol: 'Ar'}, + {position: 19, name: 'Potassium', weight: 39.0983, symbol: 'K'}, + {position: 20, name: 'Calcium', weight: 40.078, symbol: 'Ca'}, +]; diff --git a/src/material-examples/table-http/table-http-example.css b/src/material-examples/table-http/table-http-example.css index 185ff44b7ad0..4b3734dbecf0 100644 --- a/src/material-examples/table-http/table-http-example.css +++ b/src/material-examples/table-http/table-http-example.css @@ -20,23 +20,6 @@ min-height: 300px; } -.mat-column-title { - text-overflow: ellipsis; - white-space: nowrap; - flex: 1; - overflow: hidden; -} - -/* Column Widths */ -.mat-column-number, -.mat-column-state { - max-width: 64px; -} - -.mat-column-created { - max-width: 124px; -} - .example-loading-shade { position: absolute; top: 0; @@ -55,3 +38,13 @@ max-width: 360px; text-align: center; } + +/* Column Widths */ +.mat-column-number, +.mat-column-state { + max-width: 64px; +} + +.mat-column-created { + max-width: 124px; +} diff --git a/src/material-examples/table-http/table-http-example.html b/src/material-examples/table-http/table-http-example.html index a176f2f624f3..1d8fedec25e1 100644 --- a/src/material-examples/table-http/table-http-example.html +++ b/src/material-examples/table-http/table-http-example.html @@ -1,14 +1,14 @@
- -
+ *ngIf="isLoadingResults || isRateLimitReached"> + +
GitHub's API rate limit has been reached. It will be reset in one minute.
+ matSort matSortActive="created" matSortDisableClear matSortDirection="asc"> @@ -32,10 +32,10 @@ - + + mat-sort-header + disableClear="true"> Created {{ row.created_at | date }} @@ -45,7 +45,6 @@ - +
diff --git a/src/material-examples/table-http/table-http-example.ts b/src/material-examples/table-http/table-http-example.ts index 8dd5f2d36265..93c5f38dea97 100644 --- a/src/material-examples/table-http/table-http-example.ts +++ b/src/material-examples/table-http/table-http-example.ts @@ -1,7 +1,6 @@ import {Component, OnInit, ViewChild} from '@angular/core'; import {HttpClient} from '@angular/common/http'; -import {DataSource} from '@angular/cdk/collections'; -import {MatPaginator, MatSort} from '@angular/material'; +import {MatPaginator, MatSort, MatTableDataSource} from '@angular/material'; import {Observable} from 'rxjs/Observable'; import 'rxjs/add/observable/merge'; import 'rxjs/add/observable/of'; @@ -18,20 +17,48 @@ import 'rxjs/add/operator/switchMap'; styleUrls: ['table-http-example.css'], templateUrl: 'table-http-example.html', }) -export class TableHttpExample implements OnInit { - displayedColumns = ['created_at', 'state', 'number', 'title']; - exampleDatabase: ExampleHttpDataSource | null; - dataSource: ExampleDataSource | null; +export class TableHttpExample { + displayedColumns = ['created', 'state', 'number', 'title']; + exampleDatabase: ExampleHttpDao | null; + dataSource = new MatTableDataSource(); + + resultsLength = 0; + isLoadingResults = false; + isRateLimitReached = false; @ViewChild(MatPaginator) paginator: MatPaginator; @ViewChild(MatSort) sort: MatSort; - constructor(private _httpClient: HttpClient) {} + constructor(private http: HttpClient) {} - ngOnInit() { - this.exampleDatabase = new ExampleHttpDataSource(this._httpClient); - this.dataSource = new ExampleDataSource( - this.exampleDatabase!, this.paginator, this.sort); + ngAfterViewInit() { + this.exampleDatabase = new ExampleHttpDao(this.http); + + // If the user changes the sort order, reset back to the first page. + this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0); + + Observable.merge(this.sort.sortChange, this.paginator.page) + .startWith(null) + .switchMap(() => { + this.isLoadingResults = true; + return this.exampleDatabase!.getRepoIssues( + this.sort.active, this.sort.direction, this.paginator.pageIndex); + }) + .map(data => { + // Flip flag to show that loading has finished. + this.isLoadingResults = false; + this.isRateLimitReached = false; + this.resultsLength = data.total_count; + + return data.items; + }) + .catch(() => { + this.isLoadingResults = false; + // Catch if the GitHub API has reached its rate limit. Return empty data. + this.isRateLimitReached = true; + return Observable.of([]); + }) + .subscribe(data => this.dataSource.data = data); } } @@ -48,69 +75,14 @@ export interface GithubIssue { } /** An example database that the data source uses to retrieve data for the table. */ -export class ExampleHttpDataSource { - constructor(private _httpClient: HttpClient) {} +export class ExampleHttpDao { + constructor(private http: HttpClient) {} getRepoIssues(sort: string, order: string, page: number): Observable { const href = 'https://api.github.com/search/issues'; const requestUrl = - `${href}?q=repo:angular/material2&sort=${sort}&order=${order}&page=${page + 1}`; + `${href}?q=repo:angular/material2&sort=${sort}&order=${order}&page=${page + 1}`; - return this._httpClient.get(requestUrl); + return this.http.get(requestUrl); } } - -/** - * 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, ExampleHttpDao. 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 { - // The number of issues returned by github matching the query. - resultsLength = 0; - isLoadingResults = false; - isRateLimitReached = false; - - constructor(private exampleDatabase: ExampleHttpDataSource, - private paginator: MatPaginator, - private sort: MatSort) { - super(); - } - - /** Connect function called by the table to retrieve one stream containing the data to render. */ - connect(): Observable { - const displayDataChanges = [ - this.sort.sortChange, - this.paginator.page - ]; - - // If the user changes the sort order, reset back to the first page. - this.sort.sortChange.subscribe(() => this.paginator.pageIndex = 0); - - return Observable.merge(...displayDataChanges) - .startWith(null) - .switchMap(() => { - this.isLoadingResults = true; - return this.exampleDatabase.getRepoIssues( - this.sort.active, this.sort.direction, this.paginator.pageIndex); - }) - .map(data => { - // Flip flag to show that loading has finished. - this.isLoadingResults = false; - this.isRateLimitReached = false; - this.resultsLength = data.total_count; - - return data.items; - }) - .catch(() => { - this.isLoadingResults = false; - // Catch if the GitHub API has reached its rate limit. Return empty data. - this.isRateLimitReached = true; - return Observable.of([]); - }); - } - - disconnect() {} -} diff --git a/src/material-examples/table-overview/table-overview-example.css b/src/material-examples/table-overview/table-overview-example.css index c5c27f6fa424..0a4bfa776468 100644 --- a/src/material-examples/table-overview/table-overview-example.css +++ b/src/material-examples/table-overview/table-overview-example.css @@ -1,4 +1,3 @@ -/* Structure */ .example-container { display: flex; flex-direction: column; @@ -6,45 +5,13 @@ } .example-header { - min-height: 56px; - max-height: 56px; - display: flex; - align-items: center; + min-height: 64px; padding: 8px 24px 0; - font-size: 20px; - justify-content: space-between; - border-bottom: 1px solid transparent; } .mat-form-field { font-size: 14px; - flex-grow: 1; - margin-top: 8px; -} - -.example-no-results { - display: flex; - justify-content: center; - padding: 24px; - font-size: 12px; - font-style: italic; -} - -/** Selection styles */ -.example-selection-header { - font-size: 18px; -} - -.mat-column-select { - max-width: 54px; -} - -.mat-row:hover, .example-selected-row { - background: #f5f5f5; -} - -.mat-row:active, .mat-row.example-selected-row { - background: #eaeaea; + width: 100%; } .mat-table { diff --git a/src/material-examples/table-overview/table-overview-example.html b/src/material-examples/table-overview/table-overview-example.html index 847ec261256a..d1fd84fafff6 100644 --- a/src/material-examples/table-overview/table-overview-example.html +++ b/src/material-examples/table-overview/table-overview-example.html @@ -1,40 +1,15 @@ -
- - +
+ +
-
- {{selection.selected.length}} - {{selection.selected.length == 1 ? 'user' : 'users'}} - selected -
- - - - - - - - - - - - - - - + - + ID {{row.id}} @@ -46,7 +21,7 @@ - + Name {{row.name}} @@ -58,21 +33,9 @@ - + -
- 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 b9a3e0f30400..88ef1ff5c67d 100644 --- a/src/material-examples/table-overview/table-overview-example.ts +++ b/src/material-examples/table-overview/table-overview-example.ts @@ -1,18 +1,8 @@ -import {Component, ElementRef, ViewChild} from '@angular/core'; -import {DataSource} from '@angular/cdk/collections'; -import {MatPaginator, MatSort} from '@angular/material'; -import {SelectionModel} from '@angular/cdk/collections'; -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'; +import {Component, ViewChild} from '@angular/core'; +import {MatPaginator, MatSort, MatTableDataSource} from '@angular/material'; /** - * @title Feature-rich data table + * @title Data table with sorting, pagination, and filtering. */ @Component({ selector: 'table-overview-example', @@ -20,50 +10,51 @@ import 'rxjs/add/operator/debounceTime'; templateUrl: 'table-overview-example.html', }) export class TableOverviewExample { - displayedColumns = ['select', 'userId', 'userName', 'progress', 'color']; - exampleDatabase = new ExampleDatabase(); - selection = new SelectionModel(true, []); - dataSource: ExampleDataSource | null; + displayedColumns = ['id', 'name', 'progress', 'color']; + dataSource: MatTableDataSource; @ViewChild(MatPaginator) paginator: MatPaginator; @ViewChild(MatSort) sort: MatSort; - @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; } + constructor() { + // Create 100 users + const users: UserData[] = []; + for (let i = 1; i <= 100; i++) { users.push(createNewUser(i)); } - if (this.filter.nativeElement.value) { - return this.selection.selected.length == this.dataSource.renderedData.length; - } else { - return this.selection.selected.length == this.exampleDatabase.data.length; - } + // Assign the data to the data source for the table to render + this.dataSource = new MatTableDataSource(users); } - masterToggle() { - if (!this.dataSource) { return; } + /** + * Set the paginator and sort after the view init since this component will + * be able to query its view for the initialized paginator and sort. + */ + ngAfterViewInit() { + this.dataSource.paginator = this.paginator; + this.dataSource.sort = this.sort; + } - 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)); - } + applyFilter(filterValue: string) { + filterValue = filterValue.trim(); // Remove whitespace + filterValue = filterValue.toLowerCase(); // Datasource defaults to lowercase matches + this.dataSource.filter = filterValue; } } +/** Builds and returns a new User. */ +function createNewUser(id: number): UserData { + const name = + NAMES[Math.round(Math.random() * (NAMES.length - 1))] + ' ' + + NAMES[Math.round(Math.random() * (NAMES.length - 1))].charAt(0) + '.'; + + return { + id: id.toString(), + name: name, + progress: Math.round(Math.random() * 100).toString(), + color: COLORS[Math.round(Math.random() * (COLORS.length - 1))] + }; +} + /** 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']; @@ -77,112 +68,3 @@ export interface UserData { 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); } - - filteredData: UserData[] = []; - renderedData: UserData[] = []; - - constructor(private _exampleDatabase: ExampleDatabase, - private _paginator: MatPaginator, - private _sort: MatSort) { - super(); - - // Reset to the first page when the user changes the filter. - this._filterChange.subscribe(() => this._paginator.pageIndex = 0); - } - - /** 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.sortChange, - this._filterChange, - this._paginator.page, - ]; - - return Observable.merge(...displayDataChanges).map(() => { - // Filter data - 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(this.filteredData.slice()); - - // 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); - }); - } -} diff --git a/src/material-examples/table-pagination/table-pagination-example.css b/src/material-examples/table-pagination/table-pagination-example.css index 5b9032d196b3..6872a38f9642 100644 --- a/src/material-examples/table-pagination/table-pagination-example.css +++ b/src/material-examples/table-pagination/table-pagination-example.css @@ -1,18 +1,9 @@ -/* Structure */ .example-container { display: flex; flex-direction: column; min-width: 300px; } -.example-header { - min-height: 64px; - display: flex; - align-items: center; - padding-left: 24px; - font-size: 20px; -} - .mat-table { overflow: auto; max-height: 500px; diff --git a/src/material-examples/table-pagination/table-pagination-example.html b/src/material-examples/table-pagination/table-pagination-example.html index 97f7d4ac8c17..4a9a50191094 100644 --- a/src/material-examples/table-pagination/table-pagination-example.html +++ b/src/material-examples/table-pagination/table-pagination-example.html @@ -1,32 +1,28 @@
- - - - - - ID - {{row.id}} - - - - - Progress - {{row.progress}}% + + + No. + {{element.position}} - + Name - {{row.name}} + {{element.name}} + + + + + Weight + {{element.weight}} - - Color - {{row.color}} + + Symbol + {{element.symbol}} @@ -34,9 +30,7 @@ + [pageSize]="10" + [pageSizeOptions]="[5, 10, 20]"> -
+
\ 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 index 3040bfec59d8..bca8dac8093d 100644 --- a/src/material-examples/table-pagination/table-pagination-example.ts +++ b/src/material-examples/table-pagination/table-pagination-example.ts @@ -1,11 +1,5 @@ import {Component, ViewChild} from '@angular/core'; -import {DataSource} from '@angular/cdk/collections'; -import {MatPaginator} 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 {MatPaginator, MatTableDataSource} from '@angular/material'; /** * @title Table with pagination @@ -16,91 +10,46 @@ import 'rxjs/add/operator/map'; templateUrl: 'table-pagination-example.html', }) export class TablePaginationExample { - displayedColumns = ['userId', 'userName', 'progress', 'color']; - exampleDatabase = new ExampleDatabase(); - dataSource: ExampleDataSource | null; + displayedColumns = ['position', 'name', 'weight', 'symbol']; + dataSource = new MatTableDataSource(ELEMENT_DATA); @ViewChild(MatPaginator) paginator: MatPaginator; - ngOnInit() { - this.dataSource = new ExampleDataSource(this.exampleDatabase, this.paginator); + /** + * Set the paginator after the view init since this component will + * be able to query its view for the initialized paginator. + */ + ngAfterViewInit() { + this.dataSource.paginator = 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; +export interface Element { 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))] - }; - } + position: number; + weight: number; + symbol: string; } -/** - * 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: MatPaginator) { - 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() {} -} +const ELEMENT_DATA: Element[] = [ + {position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'}, + {position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'}, + {position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'}, + {position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'}, + {position: 5, name: 'Boron', weight: 10.811, symbol: 'B'}, + {position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'}, + {position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'}, + {position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'}, + {position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'}, + {position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'}, + {position: 11, name: 'Sodium', weight: 22.9897, symbol: 'Na'}, + {position: 12, name: 'Magnesium', weight: 24.305, symbol: 'Mg'}, + {position: 13, name: 'Aluminum', weight: 26.9815, symbol: 'Al'}, + {position: 14, name: 'Silicon', weight: 28.0855, symbol: 'Si'}, + {position: 15, name: 'Phosphorus', weight: 30.9738, symbol: 'P'}, + {position: 16, name: 'Sulfur', weight: 32.065, symbol: 'S'}, + {position: 17, name: 'Chlorine', weight: 35.453, symbol: 'Cl'}, + {position: 18, name: 'Argon', weight: 39.948, symbol: 'Ar'}, + {position: 19, name: 'Potassium', weight: 39.0983, symbol: 'K'}, + {position: 20, name: 'Calcium', weight: 40.078, symbol: 'Ca'}, +]; diff --git a/src/material-examples/table-sorting/table-sorting-example.css b/src/material-examples/table-sorting/table-sorting-example.css index 0ff9559b763b..c5f30cac2a1c 100644 --- a/src/material-examples/table-sorting/table-sorting-example.css +++ b/src/material-examples/table-sorting/table-sorting-example.css @@ -1,23 +1,14 @@ -/* Structure */ .example-container { display: flex; flex-direction: column; min-width: 300px; } -.example-header { - min-height: 64px; - display: flex; - align-items: center; - padding-left: 24px; - font-size: 20px; -} - .mat-table { overflow: auto; max-height: 500px; } -.mat-header-cell .mat-sort-header-sorted { +.mat-header-cell.mat-sort-header-sorted { color: black; } diff --git a/src/material-examples/table-sorting/table-sorting-example.html b/src/material-examples/table-sorting/table-sorting-example.html index ec3ed853501a..16c77d2b4e59 100644 --- a/src/material-examples/table-sorting/table-sorting-example.html +++ b/src/material-examples/table-sorting/table-sorting-example.html @@ -1,34 +1,31 @@
- - - - - ID - {{row.id}} - - - - - Progress - {{row.progress}}% + + + No. + {{element.position}} - + Name - {{row.name}} + {{element.name}} + + + + + Weight + {{element.weight}} - - Color - {{row.color}} + + Symbol + {{element.symbol}} -
+
\ 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 index 36c6eea972a6..f52722c9c99c 100644 --- a/src/material-examples/table-sorting/table-sorting-example.ts +++ b/src/material-examples/table-sorting/table-sorting-example.ts @@ -1,11 +1,5 @@ import {Component, ViewChild} from '@angular/core'; -import {DataSource} from '@angular/cdk/collections'; -import {MatSort} 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 {MatTableDataSource, MatSort} from '@angular/material'; /** * @title Table with sorting @@ -16,110 +10,46 @@ import 'rxjs/add/operator/map'; templateUrl: 'table-sorting-example.html', }) export class TableSortingExample { - displayedColumns = ['userId', 'userName', 'progress', 'color']; - exampleDatabase = new ExampleDatabase(); - dataSource: ExampleDataSource | null; + displayedColumns = ['position', 'name', 'weight', 'symbol']; + dataSource = new MatTableDataSource(ELEMENT_DATA); @ViewChild(MatSort) sort: MatSort; - ngOnInit() { - this.dataSource = new ExampleDataSource(this.exampleDatabase, this.sort); + /** + * Set the sort after the view init since this component will + * be able to query its view for the initialized sort. + */ + ngAfterViewInit() { + this.dataSource.sort = 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; +export interface Element { 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))] - }; - } + position: number; + weight: number; + symbol: string; } -/** - * 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: MatSort) { - 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.sortChange, - ]; - - 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); - }); - } -} +const ELEMENT_DATA: Element[] = [ + {position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'}, + {position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'}, + {position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'}, + {position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'}, + {position: 5, name: 'Boron', weight: 10.811, symbol: 'B'}, + {position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'}, + {position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'}, + {position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'}, + {position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'}, + {position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'}, + {position: 11, name: 'Sodium', weight: 22.9897, symbol: 'Na'}, + {position: 12, name: 'Magnesium', weight: 24.305, symbol: 'Mg'}, + {position: 13, name: 'Aluminum', weight: 26.9815, symbol: 'Al'}, + {position: 14, name: 'Silicon', weight: 28.0855, symbol: 'Si'}, + {position: 15, name: 'Phosphorus', weight: 30.9738, symbol: 'P'}, + {position: 16, name: 'Sulfur', weight: 32.065, symbol: 'S'}, + {position: 17, name: 'Chlorine', weight: 35.453, symbol: 'Cl'}, + {position: 18, name: 'Argon', weight: 39.948, symbol: 'Ar'}, + {position: 19, name: 'Potassium', weight: 39.0983, symbol: 'K'}, + {position: 20, name: 'Calcium', weight: 40.078, symbol: 'Ca'}, +];