mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
feat(table): support native table selectors (#10594)
This commit is contained in:
committed by
Joey Perrott
parent
bcff93e8e4
commit
7774da2e28
@@ -61,7 +61,7 @@ export class CdkColumnDef {
|
||||
|
||||
/** Header cell template container that adds the right classes and role. */
|
||||
@Directive({
|
||||
selector: 'cdk-header-cell',
|
||||
selector: 'cdk-header-cell, th[cdk-header-cell]',
|
||||
host: {
|
||||
'class': 'cdk-header-cell',
|
||||
'role': 'columnheader',
|
||||
@@ -75,7 +75,7 @@ export class CdkHeaderCell {
|
||||
|
||||
/** Cell template container that adds the right classes and role. */
|
||||
@Directive({
|
||||
selector: 'cdk-cell',
|
||||
selector: 'cdk-cell, td[cdk-cell]',
|
||||
host: {
|
||||
'class': 'cdk-cell',
|
||||
'role': 'gridcell',
|
||||
|
||||
@@ -151,7 +151,7 @@ export class CdkCellOutlet {
|
||||
/** Header template container that contains the cell outlet. Adds the right class and role. */
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: 'cdk-header-row',
|
||||
selector: 'cdk-header-row, tr[cdk-header-row]',
|
||||
template: CDK_ROW_TEMPLATE,
|
||||
host: {
|
||||
'class': 'cdk-header-row',
|
||||
@@ -165,7 +165,7 @@ export class CdkHeaderRow { }
|
||||
/** Data row template container that contains the cell outlet. Adds the right class and role. */
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: 'cdk-row',
|
||||
selector: 'cdk-row, tr[cdk-row]',
|
||||
template: CDK_ROW_TEMPLATE,
|
||||
host: {
|
||||
'class': 'cdk-row',
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {NgModule} from '@angular/core';
|
||||
import {HeaderRowPlaceholder, RowPlaceholder, CdkTable} from './table';
|
||||
import {CdkTable, HeaderRowPlaceholder, RowPlaceholder} from './table';
|
||||
import {CdkCellOutlet, CdkHeaderRow, CdkHeaderRowDef, CdkRow, CdkRowDef} from './row';
|
||||
import {CdkColumnDef, CdkHeaderCellDef, CdkHeaderCell, CdkCell, CdkCellDef} from './cell';
|
||||
import {CdkCell, CdkCellDef, CdkColumnDef, CdkHeaderCell, CdkHeaderCellDef} from './cell';
|
||||
|
||||
const EXPORTED_DECLARATIONS = [
|
||||
CdkTable,
|
||||
@@ -30,8 +30,8 @@ const EXPORTED_DECLARATIONS = [
|
||||
|
||||
@NgModule({
|
||||
imports: [CommonModule],
|
||||
exports: [EXPORTED_DECLARATIONS],
|
||||
declarations: [EXPORTED_DECLARATIONS]
|
||||
exports: EXPORTED_DECLARATIONS,
|
||||
declarations: EXPORTED_DECLARATIONS
|
||||
|
||||
})
|
||||
export class CdkTableModule { }
|
||||
|
||||
+66
-26
@@ -1,4 +1,4 @@
|
||||
The `<cdk-table>` is an unopinionated, customizable data-table with a fully-templated API, dynamic
|
||||
The `CdkTable` 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.
|
||||
|
||||
@@ -7,7 +7,7 @@ built. Because it enforces no opinions on these matters, developers have full co
|
||||
interaction patterns associated with the table.
|
||||
|
||||
For a Material Design styled table, see the
|
||||
[documentation for `<mat-table>`](https://material.angular.io/components/table) which builds on
|
||||
[documentation for `MatTable`](https://material.angular.io/components/table) which builds on
|
||||
top of the CDK data-table.
|
||||
|
||||
<!-- example(cdk-table-basic) -->
|
||||
@@ -23,8 +23,8 @@ the column a name. Each column definition then further defines both a header-cel
|
||||
|
||||
```html
|
||||
<ng-container cdkColumnDef="username">
|
||||
<cdk-header-cell *cdkHeaderCellDef> User name </cdk-header-cell>
|
||||
<cdk-cell *cdkCellDef="let row"> {{row.a}} </cdk-cell>
|
||||
<th cdk-header-cell *cdkHeaderCellDef> User name </th>
|
||||
<td cdk-cell *cdkCellDef="let row"> {{row.a}} </td>
|
||||
</ng-container>
|
||||
```
|
||||
|
||||
@@ -38,8 +38,8 @@ last).
|
||||
The next step is to define the table's header-row (`cdkHeaderRowDef`) and data-row (`cdkRowDef`).
|
||||
|
||||
```html
|
||||
<cdk-header-row *cdkHeaderRowDef="['username', 'age', 'title']"></cdk-header-row>
|
||||
<cdk-row *cdkRowDef="let row; columns: ['username', 'age', 'title']"></cdk-row>
|
||||
<tr cdk-header-row *cdkHeaderRowDef="['username', 'age', 'title']"></tr>
|
||||
<tr cdk-row *cdkRowDef="let row; columns: ['username', 'age', 'title']"></tr>
|
||||
```
|
||||
|
||||
These row templates accept the specific columns to be rendered via the name given to the
|
||||
@@ -53,36 +53,36 @@ above.
|
||||
##### Example: table with three columns
|
||||
|
||||
```html
|
||||
<cdk-table [dataSource]="dataSource">
|
||||
<table cdk-table [dataSource]="dataSource">
|
||||
<!-- User name Definition -->
|
||||
<ng-container cdkColumnDef="username">
|
||||
<cdk-header-cell *cdkHeaderCellDef> User name </cdk-header-cell>
|
||||
<cdk-cell *cdkCellDef="let row"> {{row.username}} </cdk-cell>
|
||||
<th cdk-header-cell *cdkHeaderCellDef> User name </th>
|
||||
<td cdk-cell *cdkCellDef="let row"> {{row.username}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Age Definition -->
|
||||
<ng-container cdkColumnDef="age">
|
||||
<cdk-header-cell *cdkHeaderCellDef> Age </cdk-header-cell>
|
||||
<cdk-cell *cdkCellDef="let row"> {{row.age}} </cdk-cell>
|
||||
<th cdk-header-cell *cdkHeaderCellDef> Age </th>
|
||||
<td cdk-cell *cdkCellDef="let row"> {{row.age}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Title Definition -->
|
||||
<ng-container cdkColumnDef="title">
|
||||
<cdk-header-cell *cdkHeaderCellDef> Title </cdk-header-cell>
|
||||
<cdk-cell *cdkCellDef="let row"> {{row.title}} </cdk-cell>
|
||||
<th cdk-header-cell *cdkHeaderCellDef> Title </th>
|
||||
<td cdk-cell *cdkCellDef="let row"> {{row.title}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Header and Row Declarations -->
|
||||
<cdk-header-row *cdkHeaderRowDef="['username', 'age', 'title']"></cdk-header-row>
|
||||
<cdk-row *cdkRowDef="let row; columns: ['username', 'age', 'title']"></cdk-row>
|
||||
</cdk-table>
|
||||
<tr cdk-header-row *cdkHeaderRowDef="['username', 'age', 'title']"></tr>
|
||||
<tr cdk-row *cdkRowDef="let row; columns: ['username', 'age', 'title']"></tr>
|
||||
</table>
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
```html
|
||||
<cdk-row *cdkRowDef="let row; columns: myDisplayedColumns"></cdk-row>
|
||||
<tr cdk-row *cdkRowDef="let row; columns: myDisplayedColumns"></tr>
|
||||
```
|
||||
|
||||
It is not required to display all the columns that are defined within the template,
|
||||
@@ -90,21 +90,21 @@ 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
|
||||
<cdk-row *cdkRowDef="let row; columns: ['age', 'username']"></cdk-row>
|
||||
<tr cdk-row *cdkRowDef="let row; columns: ['age', 'username']"></tr>
|
||||
```
|
||||
|
||||
Event and property bindings can be added directly to the row element.
|
||||
|
||||
##### Example: table with event and class binding
|
||||
```html
|
||||
<cdk-header-row *cdkHeaderRowDef="['age', 'username']"
|
||||
(click)="handleHeaderRowClick(row)">
|
||||
</cdk-header-row>
|
||||
<tr cdk-header-row *cdkHeaderRowDef="['age', 'username']"
|
||||
(click)="handleHeaderRowClick(row)">
|
||||
</tr>
|
||||
|
||||
<cdk-row *cdkRowDef="let row; columns: ['age', 'username']"
|
||||
[class.can-vote]="row.age >= 18"
|
||||
(click)="handleRowClick(row)">
|
||||
</cdk-row>
|
||||
<tr cdk-row *cdkRowDef="let row; columns: ['age', 'username']"
|
||||
[class.can-vote]="row.age >= 18"
|
||||
(click)="handleRowClick(row)">
|
||||
</tr>
|
||||
```
|
||||
|
||||
##### Styling columns
|
||||
@@ -136,5 +136,45 @@ To improve performance, a `trackBy` function can be provided to the table simila
|
||||
table how to uniquely identify rows to track how the data changes with each update.
|
||||
|
||||
```html
|
||||
<cdk-table [dataSource]="dataSource" [trackBy]="myTrackById">
|
||||
<table cdk-table [dataSource]="dataSource" [trackBy]="myTrackById">
|
||||
```
|
||||
|
||||
### Alternate HTML to using native table
|
||||
|
||||
The CDK table does not require that you use a native HTML table. If you want to have full control
|
||||
over the style of the table, it may be easier to follow an alternative template approach that does
|
||||
not use the native table element tags.
|
||||
|
||||
This alternative approach replaces the native table element tags with the CDK table directive
|
||||
selectors. For example, `<table cdk-table>` becomes `<cdk-table>`; `<tr cdk-row`> becomes
|
||||
`<cdk-row>`. The following shows a previous example using this alternative template:
|
||||
|
||||
```html
|
||||
<cdk-table [dataSource]="dataSource">
|
||||
<!-- User name Definition -->
|
||||
<ng-container cdkColumnDef="username">
|
||||
<cdk-header-cell *cdkHeaderCellDef> User name </cdk-header-cell>
|
||||
<cdk-cell *cdkCellDef="let row"> {{row.username}} </cdk-cell>
|
||||
</ng-container>
|
||||
|
||||
<!-- Age Definition -->
|
||||
<ng-container cdkColumnDef="age">
|
||||
<cdk-header-cell *cdkHeaderCellDef> Age </cdk-header-cell>
|
||||
<cdk-cell *cdkCellDef="let row"> {{row.age}} </cdk-cell>
|
||||
</ng-container>
|
||||
|
||||
<!-- Title Definition -->
|
||||
<ng-container cdkColumnDef="title">
|
||||
<cdk-header-cell *cdkHeaderCellDef> Title </cdk-header-cell>
|
||||
<cdk-cell *cdkCellDef="let row"> {{row.title}} </cdk-cell>
|
||||
</ng-container>
|
||||
|
||||
<!-- Header and Row Declarations -->
|
||||
<cdk-header-row *cdkHeaderRowDef="['username', 'age', 'title']"></cdk-header-row>
|
||||
<cdk-row *cdkRowDef="let row; columns: ['username', 'age', 'title']"></cdk-row>
|
||||
</cdk-table>
|
||||
```
|
||||
|
||||
For an example of how to render the structure as a table, see the
|
||||
[documentation for `<mat-table>`](https://material.angular.io/components/table) which includes
|
||||
the style support for this approach.
|
||||
@@ -232,6 +232,19 @@ describe('CdkTable', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should render correctly when using native HTML tags', () => {
|
||||
const thisFixture = createComponent(NativeHtmlTableApp);
|
||||
const thisTableElement = thisFixture.nativeElement.querySelector('table');
|
||||
thisFixture.detectChanges();
|
||||
|
||||
expectTableToMatchContent(thisTableElement, [
|
||||
['Column A', 'Column B', 'Column C'],
|
||||
['a_1', 'b_1', 'c_1'],
|
||||
['a_2', 'b_2', 'c_2'],
|
||||
['a_3', 'b_3', 'c_3'],
|
||||
]);
|
||||
});
|
||||
|
||||
it('should render cells even if row data is falsy', () => {
|
||||
const booleanRowCdkTableAppFixture = createComponent(BooleanRowCdkTableApp);
|
||||
booleanRowCdkTableAppFixture.detectChanges();
|
||||
@@ -1349,6 +1362,36 @@ class OuterTableApp {
|
||||
firstRow = i => i === 0;
|
||||
}
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<table cdk-table [dataSource]="dataSource">
|
||||
<ng-container cdkColumnDef="column_a">
|
||||
<th cdk-header-cell *cdkHeaderCellDef> Column A</th>
|
||||
<td cdk-cell *cdkCellDef="let row"> {{row.a}}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container cdkColumnDef="column_b">
|
||||
<th cdk-header-cell *cdkHeaderCellDef> Column B</th>
|
||||
<td cdk-cell *cdkCellDef="let row"> {{row.b}}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container cdkColumnDef="column_c">
|
||||
<th cdk-header-cell *cdkHeaderCellDef> Column C</th>
|
||||
<td cdk-cell *cdkCellDef="let row"> {{row.c}}</td>
|
||||
</ng-container>
|
||||
|
||||
<tr cdk-header-row *cdkHeaderRowDef="columnsToRender"></tr>
|
||||
<tr cdk-row *cdkRowDef="let row; columns: columnsToRender" class="customRowClass"></tr>
|
||||
</table>
|
||||
`
|
||||
})
|
||||
class NativeHtmlTableApp {
|
||||
dataSource: FakeDataSource | undefined = new FakeDataSource();
|
||||
columnsToRender = ['column_a', 'column_b', 'column_c'];
|
||||
|
||||
@ViewChild(CdkTable) table: CdkTable<TestData>;
|
||||
}
|
||||
|
||||
function getElements(element: Element, query: string): Element[] {
|
||||
return [].slice.call(element.querySelectorAll(query));
|
||||
}
|
||||
|
||||
+21
-5
@@ -49,7 +49,7 @@ import {
|
||||
*/
|
||||
@Directive({selector: '[rowPlaceholder]'})
|
||||
export class RowPlaceholder {
|
||||
constructor(public viewContainer: ViewContainerRef) { }
|
||||
constructor(public viewContainer: ViewContainerRef, public elementRef: ElementRef) { }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,7 +58,7 @@ export class RowPlaceholder {
|
||||
*/
|
||||
@Directive({selector: '[headerRowPlaceholder]'})
|
||||
export class HeaderRowPlaceholder {
|
||||
constructor(public viewContainer: ViewContainerRef) { }
|
||||
constructor(public viewContainer: ViewContainerRef, public elementRef: ElementRef) { }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,7 +83,7 @@ abstract class RowViewRef<T> extends EmbeddedViewRef<CdkCellOutletRowContext<T>>
|
||||
*/
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: 'cdk-table',
|
||||
selector: 'cdk-table, table[cdk-table]',
|
||||
exportAs: 'cdkTable',
|
||||
template: CDK_TABLE_TEMPLATE,
|
||||
host: {
|
||||
@@ -212,14 +212,18 @@ export class CdkTable<T> implements CollectionViewer, OnInit, AfterContentChecke
|
||||
|
||||
constructor(private readonly _differs: IterableDiffers,
|
||||
private readonly _changeDetectorRef: ChangeDetectorRef,
|
||||
elementRef: ElementRef,
|
||||
private readonly _elementRef: ElementRef,
|
||||
@Attribute('role') role: string) {
|
||||
if (!role) {
|
||||
elementRef.nativeElement.setAttribute('role', 'grid');
|
||||
this._elementRef.nativeElement.setAttribute('role', 'grid');
|
||||
}
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
if (this._elementRef.nativeElement.nodeName === 'TABLE') {
|
||||
this._applyNativeTableSections();
|
||||
}
|
||||
|
||||
// TODO(andrewseguin): Setup a listener for scrolling, emit the calculated view to viewChange
|
||||
this._dataDiffer = this._differs.find([]).create(this._trackByFn);
|
||||
|
||||
@@ -558,4 +562,16 @@ export class CdkTable<T> implements CollectionViewer, OnInit, AfterContentChecke
|
||||
return column.cell;
|
||||
});
|
||||
}
|
||||
|
||||
/** Adds native table sections (e.g. tbody) and moves the row placeholders into them. */
|
||||
private _applyNativeTableSections() {
|
||||
const thead = document.createElement('thead');
|
||||
const tbody = document.createElement('tbody');
|
||||
|
||||
this._elementRef.nativeElement.appendChild(thead);
|
||||
this._elementRef.nativeElement.appendChild(tbody);
|
||||
|
||||
thead.appendChild(this._headerRowPlaceholder.elementRef.nativeElement);
|
||||
tbody.appendChild(this._rowPlaceholder.elementRef.nativeElement);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
|
||||
<mat-form-field>
|
||||
<mat-label>Filter users</mat-label>
|
||||
<input matInput #filter>
|
||||
</mat-form-field>
|
||||
|
||||
<div class="demo-table-container demo-mat-table-example mat-elevation-z4 demo-selectable">
|
||||
|
||||
<table-header-demo (shiftColumns)="displayedColumns.push(displayedColumns.shift())"
|
||||
(toggleColorColumn)="toggleColorColumn()" *ngIf="selection.isEmpty()">
|
||||
|
||||
<button mat-menu-item (click)="progressSortingDisabled = !progressSortingDisabled">
|
||||
<mat-icon>sort</mat-icon>
|
||||
Toggle Progress Sorting
|
||||
</button>
|
||||
</table-header-demo>
|
||||
|
||||
<div class="example-header demo-selection-header"
|
||||
*ngIf="!selection.isEmpty()">
|
||||
{{selection.selected.length}}
|
||||
{{selection.selected.length == 1 ? 'user' : 'users'}}
|
||||
selected
|
||||
</div>
|
||||
|
||||
<table mat-table [dataSource]="dataSource"
|
||||
class="demo-table demo-selectable"
|
||||
matSort matSortActive="progress" matSortDirection="asc">
|
||||
|
||||
<!-- Checkbox Column -->
|
||||
<ng-container matColumnDef="select">
|
||||
<th mat-header-cell *matHeaderCellDef>
|
||||
<mat-checkbox (change)="$event ? masterToggle() : null"
|
||||
[disabled]="!dataSource.filteredData.length"
|
||||
[checked]="isMasterToggleChecked()"
|
||||
[indeterminate]="isMasterToggleIndeterminate()">
|
||||
</mat-checkbox>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let row">
|
||||
<mat-checkbox (click)="$event.stopPropagation()"
|
||||
(change)="$event ? selection.toggle(row) : null"
|
||||
[checked]="selection.isSelected(row)">
|
||||
</mat-checkbox>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Column Definition: ID -->
|
||||
<ng-container cdkColumnDef="userId">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> ID </th>
|
||||
<td mat-cell *matCellDef="let row"> {{row.id}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Column Definition: Progress -->
|
||||
<ng-container matColumnDef="progress">
|
||||
<th mat-header-cell
|
||||
*matHeaderCellDef
|
||||
[disabled]="progressSortingDisabled"
|
||||
mat-sort-header> Progress </th>
|
||||
<td mat-cell *matCellDef="let row">
|
||||
<div class="demo-progress-stat">{{row.progress}}%</div>
|
||||
<div class="demo-progress-indicator-container">
|
||||
<div class="demo-progress-indicator"
|
||||
[style.background]="row.progress > 50 ? 'green' : 'red'"
|
||||
[style.opacity]="getOpacity(row.progress)"
|
||||
[style.width.%]="row.progress"></div>
|
||||
</div>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Column Definition: Name -->
|
||||
<ng-container matColumnDef="userName">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
|
||||
<td mat-cell *matCellDef="let row"> {{row.name}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Column Definition: Color -->
|
||||
<ng-container matColumnDef="color">
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header>Color</th>
|
||||
<td mat-cell *matCellDef="let row" [style.color]="row.color"> {{row.color}} </td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="columns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: columns;"
|
||||
[class.selected]="selection.isSelected(row)"
|
||||
(click)="selection.toggle(row)">
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<mat-paginator [length]="_peopleDatabase.data.length"
|
||||
[pageSizeOptions]="[10, 25, 100]">
|
||||
</mat-paginator>
|
||||
</div>
|
||||
|
||||
<h3 class="demo-card-title"> CdkTable </h3>
|
||||
<mat-card class="demo-table-card">
|
||||
|
||||
<table cdk-table [dataSource]="data" class="demo-table">
|
||||
<ng-container cdkColumnDef="{{column}}" *ngFor="let column of definedColumns">
|
||||
<th cdk-header-cell *cdkHeaderCellDef> {{column}} </th>
|
||||
<td cdk-cell *cdkCellDef="let element"> {{element[column]}} </td>
|
||||
</ng-container>
|
||||
|
||||
<tr cdk-header-row *cdkHeaderRowDef="columnsToDisplay"></tr>
|
||||
<tr cdk-row *cdkRowDef="let data; columns: columnsToDisplay;"></tr>
|
||||
</table>
|
||||
</mat-card>
|
||||
|
||||
<h3 class="demo-card-title"> MatTable </h3>
|
||||
<mat-card class="demo-table-card">
|
||||
|
||||
<table mat-table [dataSource]="data" class="demo-table">
|
||||
<ng-container matColumnDef="{{column}}" *ngFor="let column of definedColumns">
|
||||
<th mat-header-cell *matHeaderCellDef> {{column}} </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element[column]}} </td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
|
||||
<tr mat-row *matRowDef="let data; columns: columnsToDisplay;"></tr>
|
||||
</table>
|
||||
</mat-card>
|
||||
|
||||
<h3 class="demo-card-title"> Native table with classes </h3>
|
||||
<mat-card class="demo-table-card">
|
||||
<table class="mat-table demo-table">
|
||||
<thead>
|
||||
<tr class="mat-header-row">
|
||||
<th class="mat-header-cell"> ID </th>
|
||||
<th class="mat-header-cell"> Name </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="mat-row">
|
||||
<td class="mat-cell"> 1 </td>
|
||||
<td class="mat-cell"> Arthur </td>
|
||||
</tr>
|
||||
<tr class="mat-row">
|
||||
<td class="mat-cell"> 2 </td>
|
||||
<td class="mat-cell"> Mike </td>
|
||||
</tr>
|
||||
<tr class="mat-row">
|
||||
<td class="mat-cell"> 3 </td>
|
||||
<td class="mat-cell"> Zephaniah </td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</mat-card>
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
.demo-table-card {
|
||||
margin: 8px 0;
|
||||
max-height: 400px;
|
||||
overflow: auto;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.demo-table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.demo-selection-header {
|
||||
height: 64px;
|
||||
background: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 24px;
|
||||
}
|
||||
|
||||
.demo-selectable {
|
||||
.mat-row:hover {
|
||||
background: #eeeeee;
|
||||
}
|
||||
.mat-row.selected {
|
||||
background: #f5f5f5;
|
||||
}
|
||||
}
|
||||
|
||||
table-header-demo {
|
||||
background: white;
|
||||
}
|
||||
|
||||
/* Progress bar styling */
|
||||
.cdk-column-progress {
|
||||
&.cdk-cell, &.mat-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: inherit;
|
||||
|
||||
.demo-progress-stat {
|
||||
width: 32px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.demo-progress-indicator-container {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.demo-progress-indicator {
|
||||
border-radius: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mat-column-select { width: 48px; }
|
||||
.mat-column-userId { width: 64px; }
|
||||
.mat-column-userName { width: 120px; }
|
||||
.mat-column-color { width: 120px; }
|
||||
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {Component, ElementRef, ViewChild} from '@angular/core';
|
||||
import {ELEMENT_DATA, Element} from '../element-data';
|
||||
import {MatPaginator, MatSort, MatTableDataSource} from '@angular/material';
|
||||
import {PeopleDatabase, UserData} from '../people-database';
|
||||
import {SelectionModel} from '@angular/cdk/collections';
|
||||
import {debounceTime, distinctUntilChanged} from 'rxjs/operators';
|
||||
import {fromEvent} from 'rxjs';
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
templateUrl: 'native-table.html',
|
||||
styleUrls: ['native-table.css'],
|
||||
})
|
||||
export class NativeTableDemo {
|
||||
definedColumns = ['name', 'weight', 'symbol', 'position'];
|
||||
columnsToDisplay = this.definedColumns;
|
||||
data: Element[] = ELEMENT_DATA.slice();
|
||||
|
||||
dataSource = new MatTableDataSource<UserData>();
|
||||
columns = ['select', 'userId', 'userName', 'progress', 'color'];
|
||||
selection = new SelectionModel<UserData>(true, []);
|
||||
@ViewChild(MatPaginator) paginator: MatPaginator;
|
||||
@ViewChild(MatSort) sort: MatSort;
|
||||
@ViewChild('filter') filter: ElementRef;
|
||||
|
||||
constructor(public _peopleDatabase: PeopleDatabase) {
|
||||
for (let i = 0; i < 3; i++) {
|
||||
this.columnsToDisplay = this.definedColumns.concat(this.columnsToDisplay);
|
||||
this.data = this.data.concat(this.data);
|
||||
}
|
||||
|
||||
this.dataSource.sortingDataAccessor = (data: UserData, property: string) => {
|
||||
switch (property) {
|
||||
case 'userId': return +data.id;
|
||||
case 'userName': return data.name;
|
||||
case 'progress': return +data.progress;
|
||||
case 'color': return data.color;
|
||||
default: return '';
|
||||
}
|
||||
};
|
||||
this.dataSource.filterPredicate =
|
||||
(data: UserData, filter: string) => data.name.indexOf(filter) != -1;
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
// Needs to be set up after the view is initialized since the data source will look at the sort
|
||||
// and paginator's initial values to know what data should be rendered.
|
||||
this.dataSource!.paginator = this.paginator;
|
||||
this.dataSource!.sort = this.sort;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.connect();
|
||||
fromEvent(this.filter.nativeElement, 'keyup')
|
||||
.pipe(
|
||||
debounceTime(150),
|
||||
distinctUntilChanged()
|
||||
).subscribe(() => {
|
||||
this.paginator.pageIndex = 0;
|
||||
this.dataSource.filter = this.filter.nativeElement.value;
|
||||
});
|
||||
}
|
||||
|
||||
connect() {
|
||||
this._peopleDatabase.initialize();
|
||||
this.dataSource!.data = this._peopleDatabase.data.slice();
|
||||
}
|
||||
|
||||
|
||||
/** Whether all filtered rows are selected. */
|
||||
isAllFilteredRowsSelected() {
|
||||
return this.dataSource.filteredData.every(data => this.selection.isSelected(data));
|
||||
}
|
||||
|
||||
/** Whether the selection it totally matches the filtered rows. */
|
||||
isMasterToggleChecked() {
|
||||
return this.selection.hasValue() &&
|
||||
this.isAllFilteredRowsSelected() &&
|
||||
this.selection.selected.length >= this.dataSource.filteredData.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether there is a selection that doesn't capture all the
|
||||
* filtered rows there are no filtered rows displayed.
|
||||
*/
|
||||
isMasterToggleIndeterminate() {
|
||||
return this.selection.hasValue() &&
|
||||
(!this.isAllFilteredRowsSelected() || !this.dataSource.filteredData.length);
|
||||
}
|
||||
|
||||
/** Selects all filtered rows if they are not all selected; otherwise clear selection. */
|
||||
masterToggle() {
|
||||
if (this.isMasterToggleChecked()) {
|
||||
this.selection.clear();
|
||||
} else {
|
||||
this.dataSource.filteredData.forEach(data => this.selection.select(data));
|
||||
}
|
||||
}
|
||||
|
||||
getOpacity(progress: number) {
|
||||
let distanceFromMiddle = Math.abs(50 - progress);
|
||||
return distanceFromMiddle / 50 + .3;
|
||||
}
|
||||
}
|
||||
@@ -10,10 +10,12 @@ import {Routes} from '@angular/router';
|
||||
import {TableDemo} from './table-demo';
|
||||
import {CustomTableDemo} from './custom-table/custom-table';
|
||||
import {DataInputTableDemo} from './data-input-table/data-input-table';
|
||||
import {NativeTableDemo} from './native-table/native-table';
|
||||
|
||||
export const TABLE_DEMO_ROUTES: Routes = [
|
||||
{path: '', redirectTo: 'main-demo', pathMatch: 'full'},
|
||||
{path: 'main-demo', component: TableDemo},
|
||||
{path: 'custom-table', component: CustomTableDemo},
|
||||
{path: 'data-input-table', component: DataInputTableDemo},
|
||||
{path: 'native-table', component: NativeTableDemo},
|
||||
];
|
||||
|
||||
@@ -30,6 +30,7 @@ import {RouterModule} from '@angular/router';
|
||||
import {WrapperTable} from './custom-table/wrapper-table';
|
||||
import {SimpleColumn} from './custom-table/simple-column';
|
||||
import {DataInputTableDemo} from './data-input-table/data-input-table';
|
||||
import {NativeTableDemo} from './native-table/native-table';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -57,6 +58,7 @@ import {DataInputTableDemo} from './data-input-table/data-input-table';
|
||||
TableHeaderDemo,
|
||||
WrapperTable,
|
||||
SimpleColumn,
|
||||
NativeTableDemo,
|
||||
],
|
||||
providers: [
|
||||
PeopleDatabase
|
||||
|
||||
@@ -17,5 +17,6 @@ export class TableDemoPage {
|
||||
{name: 'Main Page', link: 'main-demo'},
|
||||
{name: 'Custom Table', link: 'custom-table'},
|
||||
{name: 'Direct Data', link: 'data-input-table'},
|
||||
{name: 'Native Table', link: 'native-table'},
|
||||
];
|
||||
}
|
||||
|
||||
@@ -105,23 +105,24 @@
|
||||
|
||||
/* Progress bar styling */
|
||||
.cdk-column-progress {
|
||||
&.cdk-cell, &.mat-cell {
|
||||
display: flex;
|
||||
height: inherit;
|
||||
align-items: center;
|
||||
|
||||
.demo-progress-stat {
|
||||
width: 32px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.demo-progress-indicator-container {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.demo-progress-stat {
|
||||
width: 32px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.demo-progress-indicator-container {
|
||||
flex-grow: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.demo-progress-indicator {
|
||||
border-radius: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
.demo-progress-indicator {
|
||||
border-radius: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
background: mat-color($background, 'card');
|
||||
}
|
||||
|
||||
.mat-row, .mat-header-row {
|
||||
|
||||
mat-row, mat-header-row, th.mat-header-cell, td.mat-cell {
|
||||
border-bottom-color: mat-color($foreground, divider);
|
||||
}
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ export class MatColumnDef extends CdkColumnDef {
|
||||
|
||||
/** Header cell template container that adds the right classes and role. */
|
||||
@Directive({
|
||||
selector: 'mat-header-cell',
|
||||
selector: 'mat-header-cell, th[mat-header-cell]',
|
||||
host: {
|
||||
'class': 'mat-header-cell',
|
||||
'role': 'columnheader',
|
||||
@@ -66,7 +66,7 @@ export class MatHeaderCell extends CdkHeaderCell {
|
||||
|
||||
/** Cell template container that adds the right classes and role. */
|
||||
@Directive({
|
||||
selector: 'mat-cell',
|
||||
selector: 'mat-cell, td[mat-cell]',
|
||||
host: {
|
||||
'class': 'mat-cell',
|
||||
'role': 'gridcell',
|
||||
|
||||
@@ -42,7 +42,7 @@ export class MatRowDef<T> extends CdkRowDef<T> {
|
||||
/** Header template container that contains the cell outlet. Adds the right class and role. */
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: 'mat-header-row',
|
||||
selector: 'mat-header-row, tr[mat-header-row]',
|
||||
template: CDK_ROW_TEMPLATE,
|
||||
host: {
|
||||
'class': 'mat-header-row',
|
||||
@@ -57,7 +57,7 @@ export class MatHeaderRow extends CdkHeaderRow { }
|
||||
/** Data row template container that contains the cell outlet. Adds the right class and role. */
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: 'mat-row',
|
||||
selector: 'mat-row, tr[mat-row]',
|
||||
template: CDK_ROW_TEMPLATE,
|
||||
host: {
|
||||
'class': 'mat-row',
|
||||
|
||||
@@ -14,31 +14,29 @@ import {MatHeaderRow, MatHeaderRowDef, MatRow, MatRowDef} from './row';
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {MatCommonModule} from '@angular/material/core';
|
||||
|
||||
const EXPORTED_DECLARATIONS = [
|
||||
// Table
|
||||
MatTable,
|
||||
|
||||
// Template defs
|
||||
MatCellDef,
|
||||
MatHeaderCellDef,
|
||||
MatColumnDef,
|
||||
MatHeaderRowDef,
|
||||
MatRowDef,
|
||||
|
||||
// Cell directives
|
||||
MatHeaderCell,
|
||||
MatCell,
|
||||
|
||||
// Row directions
|
||||
MatHeaderRow,
|
||||
MatRow,
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [CdkTableModule, CommonModule, MatCommonModule],
|
||||
exports: [
|
||||
MatCell,
|
||||
MatCellDef,
|
||||
MatColumnDef,
|
||||
MatHeaderCell,
|
||||
MatHeaderCellDef,
|
||||
MatHeaderRow,
|
||||
MatHeaderRowDef,
|
||||
MatRow,
|
||||
MatRowDef,
|
||||
MatTable,
|
||||
],
|
||||
declarations: [
|
||||
MatCell,
|
||||
MatCellDef,
|
||||
MatColumnDef,
|
||||
MatHeaderCell,
|
||||
MatHeaderCellDef,
|
||||
MatHeaderRow,
|
||||
MatHeaderRowDef,
|
||||
MatRow,
|
||||
MatRowDef,
|
||||
MatTable,
|
||||
],
|
||||
exports: EXPORTED_DECLARATIONS,
|
||||
declarations: EXPORTED_DECLARATIONS,
|
||||
})
|
||||
export class MatTableModule {}
|
||||
|
||||
+65
-18
@@ -13,15 +13,15 @@ the table is implemented, see the
|
||||
|
||||
#### 1. Write your mat-table and provide data
|
||||
|
||||
Begin by creating a `<mat-table>` component in your template and passing in data.
|
||||
Begin by adding the `<table mat-table>` component to your template and passing in data.
|
||||
|
||||
The simplest way to provide data to the table is by passing a data array to the table's `data`
|
||||
The simplest way to provide data to the table is by passing a data array to the table's `dataSource`
|
||||
input. The table will take the array and render a row for each object in the data array.
|
||||
|
||||
```html
|
||||
<mat-table [dataSource]=”myDataArray”>
|
||||
<table mat-table [dataSource]=”myDataArray”>
|
||||
...
|
||||
</mat-table>
|
||||
</table>
|
||||
```
|
||||
|
||||
Since the table optimizes for performance, it will not automatically check for changes to the data
|
||||
@@ -44,8 +44,8 @@ Here's a simple column definition with the name `'userName'`. The header cell co
|
||||
|
||||
```html
|
||||
<ng-container matColumnDef="userName">
|
||||
<mat-header-cell *matHeaderCellDef> Name </mat-header-cell>
|
||||
<mat-cell *matCellDef="let user"> {{user.name}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef> Name </th>
|
||||
<td mat-cell *matCellDef="let user"> {{user.name}} </td>
|
||||
</ng-container>
|
||||
```
|
||||
|
||||
@@ -65,8 +65,8 @@ Then add `mat-header-row` and `mat-row` to the content of your `mat-table` and p
|
||||
column list as inputs.
|
||||
|
||||
```html
|
||||
<mat-header-row *matHeaderRowDef="columnsToDisplay"></mat-header-row>
|
||||
<mat-row *matRowDef="let myRowData; columns: columnsToDisplay"></mat-row>
|
||||
<tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
|
||||
<tr mat-row *matRowDef="let myRowData; columns: columnsToDisplay"></tr>
|
||||
```
|
||||
|
||||
Note that this list of columns provided to the rows can be in any order, not necessary the order in
|
||||
@@ -117,7 +117,7 @@ these feature to the table, check out their respective sections below.
|
||||
|
||||
#### Pagination
|
||||
|
||||
To paginate the table's data, add a `<mat-paginator>` after the `<mat-table>`.
|
||||
To paginate the table's data, add a `<mat-paginator>` after the table.
|
||||
|
||||
If you are using the `MatTableDataSource` for your table's data source, simply provide the
|
||||
`MatPaginator` to your data source. It will automatically listen for page changes made by the user
|
||||
@@ -137,14 +137,14 @@ and its interface is not tied to any one specific implementation.
|
||||
|
||||
#### Sorting
|
||||
|
||||
To add sorting behavior to the table, add the `matSort` directive to the `<mat-table>` and add
|
||||
To add sorting behavior to the table, add the `matSort` directive to the table and add
|
||||
`mat-sort-header` to each column header cell that should trigger sorting.
|
||||
|
||||
```html
|
||||
<!-- Name Column -->
|
||||
<ng-container matColumnDef="position">
|
||||
<mat-header-cell *matHeaderCellDef mat-sort-header> Name </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{element.position}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.position}} </td>
|
||||
</ng-container>
|
||||
```
|
||||
|
||||
@@ -216,23 +216,23 @@ this.selection = new SelectionModel<MyDataType>(allowMultiSelect, initialSelecti
|
||||
##### 2. Define a selection column
|
||||
|
||||
Add a column definition for displaying the row checkboxes, including a master toggle checkbox for
|
||||
the header. The column name should be added to the list of displayed columns provided to the
|
||||
`<mat-header-row>` and `<mat-row>`.
|
||||
the header. The column name should be added to the list of displayed columns provided to the
|
||||
header and data row.
|
||||
|
||||
```html
|
||||
<ng-container matColumnDef="select">
|
||||
<mat-header-cell *matHeaderCellDef>
|
||||
<th mat-header-cell *matHeaderCellDef>
|
||||
<mat-checkbox (change)="$event ? masterToggle() : null"
|
||||
[checked]="selection.hasValue() && isAllSelected()"
|
||||
[indeterminate]="selection.hasValue() && !isAllSelected()">
|
||||
</mat-checkbox>
|
||||
</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row">
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let row">
|
||||
<mat-checkbox (click)="$event.stopPropagation()"
|
||||
(change)="$event ? selection.toggle(row) : null"
|
||||
[checked]="selection.isSelected(row)">
|
||||
</mat-checkbox>
|
||||
</mat-cell>
|
||||
</td>
|
||||
</ng-container>
|
||||
```
|
||||
|
||||
@@ -278,3 +278,50 @@ Table's default role is `grid`, and it can be changed to `treegrid` through `rol
|
||||
|
||||
`mat-table` does not manage any focus/keyboard interaction on its own. Users can add desired
|
||||
focus/keyboard interactions in their application.
|
||||
|
||||
### Tables with `display: flex`
|
||||
|
||||
The `MatTable` does not require that you use a native HTML table. Instead, you can use an
|
||||
alternative approach that uses `display: flex` for the table's styles.
|
||||
|
||||
This alternative approach replaces the native table element tags with the `MatTable` directive
|
||||
selectors. For example, `<table mat-table>` becomes `<mat-table>`; `<tr mat-row`> becomes
|
||||
`<mat-row>`. The following shows a previous example using this alternative template:
|
||||
|
||||
```html
|
||||
<mat-table [dataSource]="dataSource">
|
||||
<!-- User name Definition -->
|
||||
<ng-container cdkColumnDef="username">
|
||||
<mat-header-cell *cdkHeaderCellDef> User name </mat-header-cell>
|
||||
<mat-cell *cdkCellDef="let row"> {{row.username}} </mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<!-- Age Definition -->
|
||||
<ng-container cdkColumnDef="age">
|
||||
<mat-header-cell *cdkHeaderCellDef> Age </mat-header-cell>
|
||||
<mat-cell *cdkCellDef="let row"> {{row.age}} </mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<!-- Title Definition -->
|
||||
<ng-container cdkColumnDef="title">
|
||||
<mat-header-cell *cdkHeaderCellDef> Title </mat-header-cell>
|
||||
<mat-cell *cdkCellDef="let row"> {{row.title}} </mat-cell>
|
||||
</ng-container>
|
||||
|
||||
<!-- Header and Row Declarations -->
|
||||
<mat-header-row *cdkHeaderRowDef="['username', 'age', 'title']"></mat-header-row>
|
||||
<mat-row *cdkRowDef="let row; columns: ['username', 'age', 'title']"></mat-row>
|
||||
</mat-table>
|
||||
```
|
||||
|
||||
Note that this approach means you cannot include certain native-table features such colspan/rowspan
|
||||
or have columns that resize themselves based on their content.
|
||||
|
||||
### Applying material styles to native table
|
||||
|
||||
If you want to have a Material design styled `<table>` without using the `MatTable`, simply apply
|
||||
the appropriate classes to the table elements. This may be useful if you have an existing table
|
||||
or if you do not need the additional benefits and features of the `MatTable`.
|
||||
|
||||
<!--- example(table-native-only) -->
|
||||
|
||||
@@ -2,19 +2,22 @@ $mat-header-row-height: 56px;
|
||||
$mat-row-height: 48px;
|
||||
$mat-row-horizontal-padding: 24px;
|
||||
|
||||
.mat-table {
|
||||
/**
|
||||
* Flex-based table structure
|
||||
*/
|
||||
mat-table {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.mat-header-row {
|
||||
mat-header-row {
|
||||
min-height: $mat-header-row-height;
|
||||
}
|
||||
|
||||
.mat-row {
|
||||
mat-row {
|
||||
min-height: $mat-row-height;
|
||||
}
|
||||
|
||||
.mat-row, .mat-header-row {
|
||||
mat-row, mat-header-row {
|
||||
display: flex;
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-style: solid;
|
||||
@@ -31,15 +34,15 @@ $mat-row-horizontal-padding: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.mat-cell:first-child, .mat-header-cell:first-child {
|
||||
mat-cell:first-child, mat-header-cell:first-child {
|
||||
padding-left: $mat-row-horizontal-padding;
|
||||
}
|
||||
|
||||
.mat-cell:last-child, .mat-header-cell:last-child {
|
||||
mat-cell:last-child, mat-header-cell:last-child {
|
||||
padding-right: $mat-row-horizontal-padding;
|
||||
}
|
||||
|
||||
.mat-cell, .mat-header-cell {
|
||||
mat-cell, mat-header-cell {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -47,3 +50,36 @@ $mat-row-horizontal-padding: 24px;
|
||||
word-wrap: break-word;
|
||||
min-height: inherit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Native HTML table structure
|
||||
*/
|
||||
table.mat-table {
|
||||
border-spacing: 0;
|
||||
}
|
||||
|
||||
tr.mat-header-row {
|
||||
height: $mat-header-row-height;
|
||||
}
|
||||
|
||||
tr.mat-row {
|
||||
height: $mat-row-height;
|
||||
}
|
||||
|
||||
th.mat-header-cell {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
th.mat-header-cell, td.mat-cell {
|
||||
padding: 0;
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-style: solid;
|
||||
}
|
||||
|
||||
th.mat-header-cell:first-child, td.mat-cell:first-child {
|
||||
padding-left: $mat-row-horizontal-padding;
|
||||
}
|
||||
|
||||
th.mat-header-cell:last-child, td.mat-cell:last-child {
|
||||
padding-right: $mat-row-horizontal-padding;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,12 @@ describe('MatTable', () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [MatTableModule, MatPaginatorModule, MatSortModule, NoopAnimationsModule],
|
||||
declarations: [MatTableApp, MatTableWithWhenRowApp, ArrayDataSourceMatTableApp],
|
||||
declarations: [
|
||||
MatTableApp,
|
||||
MatTableWithWhenRowApp,
|
||||
ArrayDataSourceMatTableApp,
|
||||
NativeHtmlTableApp
|
||||
],
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
@@ -49,6 +54,21 @@ describe('MatTable', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to render a table correctly with native elements', () => {
|
||||
let fixture = TestBed.createComponent(NativeHtmlTableApp);
|
||||
fixture.detectChanges();
|
||||
|
||||
const tableElement = fixture.nativeElement.querySelector('table');
|
||||
const data = fixture.componentInstance.dataSource!.data;
|
||||
expectTableToMatchContent(tableElement, [
|
||||
['Column A', 'Column B', 'Column C'],
|
||||
[data[0].a, data[0].b, data[0].c],
|
||||
[data[1].a, data[1].b, data[1].c],
|
||||
[data[2].a, data[2].b, data[2].c],
|
||||
[data[3].a, data[3].b, data[3].c],
|
||||
]);
|
||||
});
|
||||
|
||||
describe('with MatTableDataSource', () => {
|
||||
let tableElement: HTMLElement;
|
||||
let fixture: ComponentFixture<ArrayDataSourceMatTableApp>;
|
||||
@@ -350,6 +370,36 @@ class MatTableApp {
|
||||
@ViewChild(MatTable) table: MatTable<TestData>;
|
||||
}
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
<table mat-table [dataSource]="dataSource">
|
||||
<ng-container matColumnDef="column_a">
|
||||
<th mat-header-cell *matHeaderCellDef> Column A</th>
|
||||
<td mat-cell *matCellDef="let row"> {{row.a}}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="column_b">
|
||||
<th mat-header-cell *matHeaderCellDef> Column B</th>
|
||||
<td mat-cell *matCellDef="let row"> {{row.b}}</td>
|
||||
</ng-container>
|
||||
|
||||
<ng-container matColumnDef="column_c">
|
||||
<th mat-header-cell *matHeaderCellDef> Column C</th>
|
||||
<td mat-cell *matCellDef="let row"> {{row.c}}</td>
|
||||
</ng-container>
|
||||
|
||||
<tr mat-header-row *matHeaderRowDef="columnsToRender"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: columnsToRender"></tr>
|
||||
</table>
|
||||
`
|
||||
})
|
||||
class NativeHtmlTableApp {
|
||||
dataSource: FakeDataSource | null = new FakeDataSource();
|
||||
columnsToRender = ['column_a', 'column_b', 'column_c'];
|
||||
|
||||
@ViewChild(MatTable) table: MatTable<TestData>;
|
||||
}
|
||||
|
||||
|
||||
@Component({
|
||||
template: `
|
||||
|
||||
@@ -14,7 +14,7 @@ import {CDK_TABLE_TEMPLATE, CdkTable} from '@angular/cdk/table';
|
||||
*/
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
selector: 'mat-table',
|
||||
selector: 'mat-table, table[mat-table]',
|
||||
exportAs: 'matTable',
|
||||
template: CDK_TABLE_TEMPLATE,
|
||||
styleUrls: ['table.css'],
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
<div class="example-container mat-elevation-z8">
|
||||
<mat-table #table [dataSource]="dataSource">
|
||||
<table mat-table #table [dataSource]="dataSource">
|
||||
|
||||
<!--- Note that these columns can be defined in any order.
|
||||
The actual rendered columns are set as a property on the row definition" -->
|
||||
|
||||
<!-- Position Column -->
|
||||
<ng-container matColumnDef="position">
|
||||
<mat-header-cell *matHeaderCellDef> No. </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{element.position}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef> No. </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.position}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Name Column -->
|
||||
<ng-container matColumnDef="name">
|
||||
<mat-header-cell *matHeaderCellDef> Name </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{element.name}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef> Name </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Weight Column -->
|
||||
<ng-container matColumnDef="weight">
|
||||
<mat-header-cell *matHeaderCellDef> Weight </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{element.weight}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef> Weight </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.weight}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Symbol Column -->
|
||||
<ng-container matColumnDef="symbol">
|
||||
<mat-header-cell *matHeaderCellDef> Symbol </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{element.symbol}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef> Symbol </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.symbol}} </td>
|
||||
</ng-container>
|
||||
|
||||
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
|
||||
</mat-table>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@@ -5,33 +5,33 @@
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<mat-table #table [dataSource]="dataSource">
|
||||
<table mat-table #table [dataSource]="dataSource">
|
||||
|
||||
<!-- Position Column -->
|
||||
<ng-container matColumnDef="position">
|
||||
<mat-header-cell *matHeaderCellDef> No. </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{element.position}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef> No. </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.position}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Name Column -->
|
||||
<ng-container matColumnDef="name">
|
||||
<mat-header-cell *matHeaderCellDef> Name </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{element.name}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef> Name </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Weight Column -->
|
||||
<ng-container matColumnDef="weight">
|
||||
<mat-header-cell *matHeaderCellDef> Weight </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{element.weight}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef> Weight </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.weight}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Symbol Column -->
|
||||
<ng-container matColumnDef="symbol">
|
||||
<mat-header-cell *matHeaderCellDef> Symbol </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{element.symbol}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef> Symbol </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.symbol}} </td>
|
||||
</ng-container>
|
||||
|
||||
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
|
||||
</mat-table>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<mat-table #table [dataSource]="dataSource" class="example-table"
|
||||
<table mat-table #table [dataSource]="dataSource" class="example-table"
|
||||
matSort matSortActive="created" matSortDisableClear matSortDirection="asc">
|
||||
|
||||
<!--- Note that these columns can be defined in any order.
|
||||
@@ -15,35 +15,35 @@
|
||||
|
||||
<!-- Number Column -->
|
||||
<ng-container matColumnDef="number">
|
||||
<mat-header-cell *matHeaderCellDef>#</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row">{{ row.number }}</mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef>#</th>
|
||||
<td mat-cell *matCellDef="let row">{{ row.number }}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Title Column -->
|
||||
<ng-container matColumnDef="title">
|
||||
<mat-header-cell *matHeaderCellDef>Title</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row">{{ row.title }}</mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef>Title</th>
|
||||
<td mat-cell *matCellDef="let row">{{ row.title }}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- State Column -->
|
||||
<ng-container matColumnDef="state">
|
||||
<mat-header-cell *matHeaderCellDef>State</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row">{{ row.state }}</mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef>State</th>
|
||||
<td mat-cell *matCellDef="let row">{{ row.state }}</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Created Column -->
|
||||
<ng-container matColumnDef="created">
|
||||
<mat-header-cell *matHeaderCellDef
|
||||
<th mat-header-cell *matHeaderCellDef
|
||||
mat-sort-header
|
||||
disableClear="true">
|
||||
Created
|
||||
</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row">{{ row.created_at | date }}</mat-cell>
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let row">{{ row.created_at | date }}</td>
|
||||
</ng-container>
|
||||
|
||||
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
|
||||
</mat-table>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
|
||||
<mat-paginator [length]="resultsLength" [pageSize]="30">
|
||||
</mat-paginator>
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<table class="mat-table">
|
||||
<thead>
|
||||
<tr class="mat-header-row">
|
||||
<th class="mat-header-cell"> No. </th>
|
||||
<th class="mat-header-cell"> Name </th>
|
||||
<th class="mat-header-cell"> Weight </th>
|
||||
<th class="mat-header-cell"> Symbol </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr class="mat-row" *ngFor="let element of elements">
|
||||
<td class="mat-cell"> {{element.position}} </td>
|
||||
<td class="mat-cell"> {{element.name}} </td>
|
||||
<td class="mat-cell"> {{element.weight}} </td>
|
||||
<td class="mat-cell"> {{element.symbol}} </td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -0,0 +1,19 @@
|
||||
import {Component} from '@angular/core';
|
||||
|
||||
/**
|
||||
* @title Native `<table>` that only applies the Material styles
|
||||
*/
|
||||
@Component({
|
||||
selector: 'table-native-only-example',
|
||||
styleUrls: ['table-native-only-example.css'],
|
||||
templateUrl: 'table-native-only-example.html',
|
||||
})
|
||||
export class TableNativeOnlyExample {
|
||||
elements = [
|
||||
{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'},
|
||||
];
|
||||
}
|
||||
@@ -6,36 +6,36 @@
|
||||
|
||||
<div class="example-container mat-elevation-z8">
|
||||
|
||||
<mat-table [dataSource]="dataSource" matSort>
|
||||
<table mat-table [dataSource]="dataSource" matSort>
|
||||
|
||||
<!-- ID Column -->
|
||||
<ng-container matColumnDef="id">
|
||||
<mat-header-cell *matHeaderCellDef mat-sort-header> ID </mat-header-cell>
|
||||
<mat-cell *matCellDef="let row"> {{row.id}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> ID </th>
|
||||
<td mat-cell *matCellDef="let row"> {{row.id}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Progress Column -->
|
||||
<ng-container matColumnDef="progress">
|
||||
<mat-header-cell *matHeaderCellDef mat-sort-header> Progress </mat-header-cell>
|
||||
<mat-cell *matCellDef="let row"> {{row.progress}}% </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Progress </th>
|
||||
<td mat-cell *matCellDef="let row"> {{row.progress}}% </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Name Column -->
|
||||
<ng-container matColumnDef="name">
|
||||
<mat-header-cell *matHeaderCellDef mat-sort-header> Name </mat-header-cell>
|
||||
<mat-cell *matCellDef="let row"> {{row.name}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
|
||||
<td mat-cell *matCellDef="let row"> {{row.name}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Color Column -->
|
||||
<ng-container matColumnDef="color">
|
||||
<mat-header-cell *matHeaderCellDef mat-sort-header> Color </mat-header-cell>
|
||||
<mat-cell *matCellDef="let row" [style.color]="row.color"> {{row.color}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Color </th>
|
||||
<td mat-cell *matCellDef="let row" [style.color]="row.color"> {{row.color}} </td>
|
||||
</ng-container>
|
||||
|
||||
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns;">
|
||||
</mat-row>
|
||||
</mat-table>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;">
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<mat-paginator [pageSizeOptions]="[5, 10, 25, 100]"></mat-paginator>
|
||||
</div>
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
<div class="example-container mat-elevation-z8">
|
||||
<mat-table #table [dataSource]="dataSource">
|
||||
<table mat-table #table [dataSource]="dataSource">
|
||||
|
||||
<!-- Position Column -->
|
||||
<ng-container matColumnDef="position">
|
||||
<mat-header-cell *matHeaderCellDef> No. </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{element.position}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef> No. </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.position}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Name Column -->
|
||||
<ng-container matColumnDef="name">
|
||||
<mat-header-cell *matHeaderCellDef> Name </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{element.name}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef> Name </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Weight Column -->
|
||||
<ng-container matColumnDef="weight">
|
||||
<mat-header-cell *matHeaderCellDef> Weight </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{element.weight}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef> Weight </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.weight}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Symbol Column -->
|
||||
<ng-container matColumnDef="symbol">
|
||||
<mat-header-cell *matHeaderCellDef> Symbol </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{element.symbol}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef> Symbol </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.symbol}} </td>
|
||||
</ng-container>
|
||||
|
||||
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
|
||||
</mat-table>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
|
||||
<mat-paginator #paginator
|
||||
[pageSize]="10"
|
||||
|
||||
@@ -1,49 +1,49 @@
|
||||
<div class="example-container mat-elevation-z8">
|
||||
<mat-table #table [dataSource]="dataSource">
|
||||
<table mat-table #table [dataSource]="dataSource">
|
||||
|
||||
<!-- Checkbox Column -->
|
||||
<ng-container matColumnDef="select">
|
||||
<mat-header-cell *matHeaderCellDef>
|
||||
<th mat-header-cell *matHeaderCellDef>
|
||||
<mat-checkbox (change)="$event ? masterToggle() : null"
|
||||
[checked]="selection.hasValue() && isAllSelected()"
|
||||
[indeterminate]="selection.hasValue() && !isAllSelected()">
|
||||
</mat-checkbox>
|
||||
</mat-header-cell>
|
||||
<mat-cell *matCellDef="let row">
|
||||
</th>
|
||||
<td mat-cell *matCellDef="let row">
|
||||
<mat-checkbox (click)="$event.stopPropagation()"
|
||||
(change)="$event ? selection.toggle(row) : null"
|
||||
[checked]="selection.isSelected(row)">
|
||||
</mat-checkbox>
|
||||
</mat-cell>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Position Column -->
|
||||
<ng-container matColumnDef="position">
|
||||
<mat-header-cell *matHeaderCellDef> No. </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{element.position}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef> No. </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.position}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Name Column -->
|
||||
<ng-container matColumnDef="name">
|
||||
<mat-header-cell *matHeaderCellDef> Name </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{element.name}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef> Name </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Weight Column -->
|
||||
<ng-container matColumnDef="weight">
|
||||
<mat-header-cell *matHeaderCellDef> Weight </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{element.weight}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef> Weight </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.weight}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Symbol Column -->
|
||||
<ng-container matColumnDef="symbol">
|
||||
<mat-header-cell *matHeaderCellDef> Symbol </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{element.symbol}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef> Symbol </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.symbol}} </td>
|
||||
</ng-container>
|
||||
|
||||
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns;"
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"
|
||||
(click)="selection.toggle(row)">
|
||||
</mat-row>
|
||||
</mat-table>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
<div class="example-container mat-elevation-z8">
|
||||
<mat-table #table [dataSource]="dataSource" matSort>
|
||||
<table mat-table #table [dataSource]="dataSource" matSort>
|
||||
|
||||
<!-- Position Column -->
|
||||
<ng-container matColumnDef="position">
|
||||
<mat-header-cell *matHeaderCellDef mat-sort-header> No. </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{element.position}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> No. </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.position}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Name Column -->
|
||||
<ng-container matColumnDef="name">
|
||||
<mat-header-cell *matHeaderCellDef mat-sort-header> Name </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{element.name}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Name </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.name}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Weight Column -->
|
||||
<ng-container matColumnDef="weight">
|
||||
<mat-header-cell *matHeaderCellDef mat-sort-header> Weight </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{element.weight}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Weight </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.weight}} </td>
|
||||
</ng-container>
|
||||
|
||||
<!-- Symbol Column -->
|
||||
<ng-container matColumnDef="symbol">
|
||||
<mat-header-cell *matHeaderCellDef mat-sort-header> Symbol </mat-header-cell>
|
||||
<mat-cell *matCellDef="let element"> {{element.symbol}} </mat-cell>
|
||||
<th mat-header-cell *matHeaderCellDef mat-sort-header> Symbol </th>
|
||||
<td mat-cell *matCellDef="let element"> {{element.symbol}} </td>
|
||||
</ng-container>
|
||||
|
||||
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
|
||||
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
|
||||
</mat-table>
|
||||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
|
||||
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user