|
1 |
| -The `mat-table` provides a Material Design styled data-table that can be used to display rows of |
2 |
| -data. |
| 1 | +The `mat-table` provides a Material Design styled data-table that can be used to display rows of |
| 2 | +data. |
3 | 3 |
|
4 |
| -This table builds on the foundation of the CDK data-table and uses a similar interface for its |
5 |
| -data source input and template, except that its element and attribute selectors will be prefixed |
6 |
| -with `mat-` instead of `cdk-`. |
| 4 | +The table's template consists of two parts: column definitions and row definitions. Each column |
| 5 | +definition contains templates for that column's header and content cells. Each row definition |
| 6 | +captures the columns used for that row and any bindings applied to the row element. |
| 7 | + |
| 8 | +A `DataSource` provides data to the table by emitting an `Observable` stream of the items to be |
| 9 | +rendered. Each emit includes the _entire set of items_ that should be displayed. The table, |
| 10 | +listening to this stream, will render a row per item. Any manipulation of the data being displayed |
| 11 | +(e.g. sorting, pagination, filtering) should be captured by the `DataSource`, ultimately emitting |
| 12 | +a new set of items to reflect any changes. |
7 | 13 |
|
8 |
| -For more information on the interface and how it works, see the |
| 14 | +This table builds on the foundation of the CDK data-table and uses a similar interface for its |
| 15 | +data source input and template, except that its element and attribute selectors will be prefixed |
| 16 | +with `mat-` instead of `cdk-`. For detailed information on the interface and how it works, see the |
9 | 17 | [guide covering the CDK data-table](https://material.angular.io/guide/cdk-table).
|
10 | 18 |
|
| 19 | +### Getting Started |
| 20 | + |
11 | 21 | <!-- example(table-basic) -->
|
12 | 22 |
|
13 |
| -### Features |
| 23 | +### 1. Define the table's columns |
| 24 | + |
| 25 | +Start by writing your table's column definitions. Each column definition should be given a unique |
| 26 | +name and contain the content for its header and row cells. |
| 27 | + |
| 28 | +Here's a simple column definition with the name `'userName'`. The header cell contains the text |
| 29 | +"Name" and each row cell will render the `name` property of each row's data. |
14 | 30 |
|
15 |
| -The `<mat-table>` itself only deals with the rendering of a table structure (rows and cells). |
16 |
| -Additional features can be built on top of the table by adding behavior inside cell templates |
17 |
| -(e.g., sort headers) or next to the table (e.g. a paginator). Interactions that affect the |
18 |
| -rendered data (such as sorting and pagination) should be propagated through the table's data source. |
| 31 | +```html |
| 32 | +<ng-container matColumnDef="userName"> |
| 33 | + <mat-header-cell *matHeaderCellDef> Name </mat-header-cell> |
| 34 | + <mat-cell *matCellDef="let user"> {{user.name}} </mat-cell> |
| 35 | +</ng-container> |
| 36 | +``` |
19 | 37 |
|
| 38 | +### 2. Define the table's rows |
| 39 | + |
| 40 | +After defining your columns, provide the header and data row templates that will be rendered out by |
| 41 | +the table. Each row needs to be given a list of the columns that it should contain. The order of |
| 42 | +the names will define the order of the cells rendered. It is not required to provide a list of all |
| 43 | +the defined column names, but only the ones that you want to have rendered. |
| 44 | + |
| 45 | +```html |
| 46 | +<mat-header-row *matHeaderRowDef="['userName', 'age']"></mat-header-row> |
| 47 | +<mat-row *matRowDef="let myRowData; columns: ['userName', 'age']"></mat-row> |
| 48 | +``` |
| 49 | + |
| 50 | +### 3. Provide data |
| 51 | + |
| 52 | +The column and row definitions now capture _how_ data will render - all that's left is to provide |
| 53 | +the data itself. For simple scenarios with client-side operations, `MatTableDataSource` offers a |
| 54 | +quick and easy starting point. Simply create an instance of `MatTableDataSource` and set the items |
| 55 | +to be displayed to the `data` property. For more advanced scenarios, applications will implement |
| 56 | +one or more custom `DataSource` to capture more specific behaviors. |
| 57 | + |
| 58 | +```ts |
| 59 | +this.myDataSource = new MatTableDataSource(); |
| 60 | +this.myDataSource.data = dataToRender; |
| 61 | +``` |
| 62 | + |
| 63 | +```html |
| 64 | +<mat-table [dataSource]=”myDataSource”> |
| 65 | + ... |
| 66 | +</mat-table> |
| 67 | +``` |
| 68 | + |
| 69 | +### Features |
20 | 70 |
|
21 | 71 | #### Pagination
|
22 | 72 |
|
23 |
| -The `<mat-paginator>` adds a pagination UI that can be used in conjunction with the `<mat-table>`. The |
24 |
| -paginator emits events that can be used to trigger an update via the table's data source. |
| 73 | +To paginate the table's data, add a `<mat-paginator>` after the `<mat-table>` and provide the |
| 74 | +`MatPaginator` to the `MatTableDataSource`. The data source will automatically listen for page |
| 75 | +changes made by the user and send the right paged data to the table. |
| 76 | + |
| 77 | +For more information on using and configuring the `<mat-paginator>`, check out the |
| 78 | +[mat-paginator docs](https://material.angular.io/components/paginator/overview). |
| 79 | + |
| 80 | +The `MatPaginator` is one provided solution to paginating your table's data, but it is not the only |
| 81 | +option. In fact, the table can work with any custom pagination UI or strategy since the `MatTable` and `DataSource` interface is not tied to any one specific implementation. |
25 | 82 |
|
26 | 83 | <!-- example(table-pagination) -->
|
27 | 84 |
|
28 | 85 | #### Sorting
|
29 | 86 |
|
30 |
| -Use the `matSort` directive and `<mat-sort-header>` adds a sorting UI the table's column headers. The |
31 |
| -sort headers emit events that can be used to trigger an update via the table's data source. |
| 87 | +To add sorting behavior to the table, add the `matSort` directive to the `<mat-table>` and add |
| 88 | +`mat-sort-header` to each column header cell that should trigger sorting. Provide the `MatSort` directive to the `MatTableDataSource` and it will automatically listen for sorting changes and change the order of data rendered by the table. |
| 89 | + |
| 90 | +By default, the `MatTableDataSource` sorts with the assumption that the sorted column's name |
| 91 | +matches the data property name that the column displays. For example, the following column definition is named `position`, which matches the name of the property displayed in the row cell. |
| 92 | + |
| 93 | +```html |
| 94 | +<!-- Name Column --> |
| 95 | +<ng-container matColumnDef="position"> |
| 96 | + <mat-header-cell *matHeaderCellDef mat-sort-header> Name </mat-header-cell> |
| 97 | + <mat-cell *matCellDef="let element"> {{element.position}} </mat-cell> |
| 98 | +</ng-container> |
| 99 | +``` |
| 100 | + |
| 101 | +If the data properties do not match the column names, or if a more complex data property accessor |
| 102 | +is required, then a custom `sortingDataAccessor` function can be set to override the default data accessor on the `MatTableDataSource`. |
32 | 103 |
|
33 | 104 | <!-- example(table-sorting) -->
|
34 | 105 |
|
| 106 | +For more information on using and configuring the sorting behavior, check out the |
| 107 | +[matSort docs](https://material.angular.io/components/sort/overview). |
| 108 | + |
| 109 | +The `MatSort` is one provided solution to sorting your table's data, but it is not the only option. |
| 110 | +In fact, the table can work with any custom pagination UI or strategy since the `MatTable` and `DataSource` interface is not tied to any one specific implementation. |
| 111 | + |
35 | 112 | #### Filtering
|
36 | 113 |
|
37 |
| -While Angular Material does not offer a specific component for filtering tabular data, the table's |
38 |
| -data source can be updated based on any custom filter UI. Any filtering pattern need only trigger |
39 |
| -an update via the table's data source. |
| 114 | +Angular Material does not provide a specific component to be used for filtering the `MatTable` |
| 115 | +since there is no single common approach to adding a filter UI to table data. |
40 | 116 |
|
41 |
| -<!--- example(table-filtering) --> |
| 117 | +A general strategy is to add an input where users can type in a filter string and listen to this |
| 118 | +input to change what data is offered from the data source to the table. |
| 119 | + |
| 120 | +If you are using the `MatTableDataSource`, simply provide the filter string to the |
| 121 | +`MatTableDataSource`. The data source will reduce each row data to a serialized form and will filter out the row if it does not contain the filter string. By default, the row data reducing function will concatenate all the object values and convert them to lowercase. |
42 | 122 |
|
43 |
| -### Simple Table |
| 123 | +For example, the data object `{id: 123, name: 'Mr. Smith', favoriteColor: 'blue'}` will be reduced |
| 124 | +to `123mr. smithblue`. If your filter string was `blue` then it would be considered a match because it is contained in the reduced string, and the row would be displayed in the table. |
| 125 | + |
| 126 | +To override the default filtering behavior, a custom `filterPredicate` function can be set which |
| 127 | +takes a data object and filter string and returns true if the data object is considered a match. |
| 128 | + |
| 129 | +<!--- example(table-filtering) --> |
44 | 130 |
|
45 |
| -In the near future, we will provide a simplified version of the data-table with an easy-to-use |
46 |
| -interface, material styling, array input, and more out-of-the-box features (sorting, pagination, |
47 |
| -and selection). |
| 131 | +#### Selection |
| 132 | + |
| 133 | +Right now there is no formal support for adding a selection UI to the table, but Angular Material |
| 134 | +does offer the right components and pieces to set this up. The following steps are one solution but it is not the only way to incorporate row selection in your table. |
| 135 | + |
| 136 | +### 1. Add a selection model |
| 137 | + |
| 138 | +Get started by setting up a `SelectionModel` from `@angular/cdk/collections` that will maintain the |
| 139 | +selection state. |
| 140 | + |
| 141 | +```js |
| 142 | +const initialSelection = []; |
| 143 | +const allowMultiSelect = true; |
| 144 | +this.selection = new SelectionModel<MyDataType>(allowMultiSelect, initialSelection); |
| 145 | +``` |
| 146 | + |
| 147 | +### 2. Define a selection column |
| 148 | + |
| 149 | +Add a column definition for displaying the row checkboxes, including a master toggle checkbox for |
| 150 | +the header. The column name should be added to the list of displayed columns provided to the `<mat-header-row>` and `<mat-row>`. |
| 151 | + |
| 152 | +```html |
| 153 | +<ng-container matColumnDef="select"> |
| 154 | + <mat-header-cell *matHeaderCellDef> |
| 155 | + <mat-checkbox (change)="$event ? masterToggle() : null" |
| 156 | + [checked]="selection.hasValue() && isAllSelected()" |
| 157 | + [indeterminate]="selection.hasValue() && !isAllSelected()"> |
| 158 | + </mat-checkbox> |
| 159 | + </mat-header-cell> |
| 160 | + <mat-cell *matCellDef="let row"> |
| 161 | + <mat-checkbox (click)="$event.stopPropagation()" |
| 162 | + (change)="$event ? selection.toggle(row) : null" |
| 163 | + [checked]="selection.isSelected(row)"> |
| 164 | + </mat-checkbox> |
| 165 | + </mat-cell> |
| 166 | +</ng-container> |
| 167 | +``` |
| 168 | + |
| 169 | +### 3. Add event handling logic |
| 170 | + |
| 171 | +Implement the behavior in your component's logic to handle the header's master toggle and checking |
| 172 | +if all rows are selected. |
| 173 | + |
| 174 | +```js |
| 175 | +/** Whether the number of selected elements matches the total number of rows. */ |
| 176 | +isAllSelected() { |
| 177 | + const numSelected = this.selection.selected.length; |
| 178 | + const numRows = this.dataSource.data.length; |
| 179 | + return numSelected == numRows; |
| 180 | +} |
| 181 | + |
| 182 | +/** Selects all rows if they are not all selected; otherwise clear selection. */ |
| 183 | +masterToggle() { |
| 184 | + this.isAllSelected() ? |
| 185 | + this.selection.clear() : |
| 186 | + this.dataSource.data.forEach(row => this.selection.select(row)); |
| 187 | +} |
| 188 | +``` |
| 189 | + |
| 190 | +### 4. Include overflow styling |
| 191 | + |
| 192 | +Finally, adjust the styling for the select column so that its overflow is not hidden. This allows |
| 193 | +the ripple effect to extend beyond the cell. |
| 194 | + |
| 195 | +```css |
| 196 | +.mat-column-select { |
| 197 | + overflow: initial; |
| 198 | +} |
| 199 | +``` |
| 200 | + |
| 201 | +<!--- example(table-selection) --> |
48 | 202 |
|
49 | 203 | ### Accessibility
|
50 |
| -Tables without text or labels should be given a meaningful label via `aria-label` or |
| 204 | +Tables without text or labels should be given a meaningful label via `aria-label` or |
51 | 205 | `aria-labelledby`. The `aria-readonly` defaults to `true` if it's not set.
|
52 | 206 |
|
53 | 207 | Table's default role is `grid`, and it can be changed to `treegrid` through `role` attribute.
|
54 | 208 |
|
55 |
| -`mat-table` does not manage any focus/keyboard interaction on its own. Users can add desired |
| 209 | +`mat-table` does not manage any focus/keyboard interaction on its own. Users can add desired |
56 | 210 | focus/keyboard interactions in their application.
|
0 commit comments