如何使用material2数据table
How to use material2 data table
我正在尝试实施 Material2 data table。但是我无法理解如何以正确的方式使用它。
import {Component, ElementRef, ViewChild} from '@angular/core';
import {DataSource} from '@angular/cdk';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/observable/merge';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/observable/fromEvent';
@Component({
selector: 'table-filtering-example',
styleUrls: ['table-filtering-example.css'],
templateUrl: 'table-filtering-example.html',
})
export class TableFilteringExample {
displayedColumns = ['userId', 'userName', 'progress', 'color'];
exampleDatabase = new ExampleDatabase();
dataSource: ExampleDataSource | null;
@ViewChild('filter') filter: ElementRef;
ngOnInit() {
this.dataSource = new ExampleDataSource(this.exampleDatabase);
Observable.fromEvent(this.filter.nativeElement, 'keyup')
.debounceTime(150)
.distinctUntilChanged()
.subscribe(() => {
if (!this.dataSource) { return; }
this.dataSource.filter = this.filter.nativeElement.value;
});
}
}
/** Constants used to fill up our data base. */
const COLORS = ['maroon', 'red', 'orange', 'yellow', 'olive', 'green', 'purple',
'fuchsia', 'lime', 'teal', 'aqua', 'blue', 'navy', 'black', 'gray'];
const NAMES = ['Maia', 'Asher', 'Olivia', 'Atticus', 'Amelia', 'Jack',
'Charlotte', 'Theodore', 'Isla', 'Oliver', 'Isabella', 'Jasper',
'Cora', 'Levi', 'Violet', 'Arthur', 'Mia', 'Thomas', 'Elizabeth'];
export interface UserData {
id: string;
name: string;
progress: string;
color: string;
}
/** An example database that the data source uses to retrieve data for the table. */
export class ExampleDatabase {
/** Stream that emits whenever the data has been modified. */
dataChange: BehaviorSubject<UserData[]> = new BehaviorSubject<UserData[]>([]);
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<any> {
_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<UserData[]> {
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() {}
}
上面是datatable的代码,让我很迷惑。甚至他们的文档也很差。有人可以解释一下上面代码的流程吗?
如果您觉得问题太基础,请忽略?
您示例中的代码是通用 table 的定义,使用 material2 规范中的新 cdk 组件。
你必须记住 md-table
是 cdk-table
的可视化实现,所以你需要声明一个 cdk,其模型与 HTML.[=40= 中的 md-model 兼容]
例如:
我声明一个 cdk-table
实现如下:
- 首先是依赖:
Material2中的新CDK组件,使用:
import { DataSource } from '@angular/cdk';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/observable/merge';
import 'rxjs/add/operator/map';
- TS中HTML的结构定义:
我定义了一个displayedColumns
数组,项目是我HTMLtable中的列,顺序是:
displayedColumns = ['userId', 'userName', 'progress'];
ExampleDatabase
类型的数据库(具有特定手动定义的对象):
exampleDatabase = new ExampleDatabase();
最后声明一个dataSource
,这是我数据的来源。是手动定义或数据为空的对象。
dataSource: ExampleDataSource | null;
在ngOnInit()
方法中,我简单地声明我的dataSource
是一个新的ExampleDataSource
,参数是我的exampleDataBase
.
很好,现在开始执行剩余的代码:
首先,为 DataBase
声明一个接口。这对于保持数据的一致性非常重要,数据库必须遵守定义的方案。
在这个例子中,数据库有三列:id、name 和 progress:
export interface UserData {
id: number;
name: string;
progress: string;
}
下一步是用我的DataBase
中的数据定义创建一个class(对象)ExampleDatabase
。您可以创建一个连接到实际数据库(PostgreSQL,MongoDB)的服务,获取真实数据并在另一种方法中为 cdk-datatable 创建对象,但是在这个例子中我们使用在 运行 时间模拟的内存数据库。
export class ExampleDatabase {
/** Stream that emits whenever the data has been modified. */
dataChange: BehaviorSubject<UserData[]> = new BehaviorSubject<UserData[]>([]);
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() {
return {
id: 1,
name: 'example',
progress: Math.round(Math.random() * 100).toString()
};
}
}
很好,我终于用 DataSource
.
的定义创建了第二个 class
export class ExampleDataSource extends DataSource<any> {
constructor(private _exampleDatabase: ExampleDatabase) {
super();
}
/** Connect function called by the table to retrieve one stream containing the data to render. */
connect(): Observable<UserData[]> {
return this._exampleDatabase.dataChange;
}
disconnect() { }
}
此方法确保数据格式正确,并将"connection"释放到DataBase
(在内存中)以获取其中的数据。
最后,在HTML中使用md-table
组件或cdk-table
组件。 md-table
组件使用material设计风格,cdk-table
使用通用风格..
md-table:
<div class="example-container mat-elevation-z8">
<md-table #table [dataSource]="dataSource">
<!-- ID Column -->
<ng-container cdkColumnDef="userId">
<md-header-cell *cdkHeaderCellDef> ID </md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.id}} </md-cell>
</ng-container>
<!-- Progress Column -->
<ng-container cdkColumnDef="progress">
<md-header-cell *cdkHeaderCellDef> Progress </md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.progress}}% </md-cell>
</ng-container>
<!-- Name Column -->
<ng-container cdkColumnDef="userName">
<md-header-cell *cdkHeaderCellDef> Name </md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.name}} </md-cell>
</ng-container>
<md-header-row *cdkHeaderRowDef="displayedColumns"></md-header-row>
<md-row *cdkRowDef="let row; columns: displayedColumns;"></md-row>
</md-table>
</div>
cdk-table:
<div class="example-container mat-elevation-z8">
<cdk-table #table [dataSource]="dataSource" class="example-table">
<!-- ID Column -->
<ng-container cdkColumnDef="userId">
<cdk-header-cell *cdkHeaderCellDef class="example-header-cell"> ID </cdk-header-cell>
<cdk-cell *cdkCellDef="let row" class="example-cell"> {{row.id}} </cdk-cell>
</ng-container>
<!-- Progress Column -->
<ng-container cdkColumnDef="progress">
<cdk-header-cell *cdkHeaderCellDef class="example-header-cell"> Progress </cdk-header-cell>
<cdk-cell *cdkCellDef="let row" class="example-cell"> {{row.progress}}% </cdk-cell>
</ng-container>
<!-- Name Column -->
<ng-container cdkColumnDef="userName">
<cdk-header-cell *cdkHeaderCellDef class="example-header-cell"> Name </cdk-header-cell>
<cdk-cell *cdkCellDef="let row" class="example-cell"> {{row.name}} </cdk-cell>
</ng-container>
<cdk-header-row *cdkHeaderRowDef="displayedColumns" class="example-header-row"></cdk-header-row>
<cdk-row *cdkRowDef="let row; columns: displayedColumns;" class="example-row"></cdk-row>
</cdk-table>
</div>
其余的实现、搜索、菜单、复选框等,由您负责实现处理信息的逻辑。
使用有关 cdk-table 的文档了解更多详情:
https://material.angular.io/guide/cdk-table
结果:
Do me saber and achievement,我理解我的解释,我为我的英语道歉。我在学习。
这是为观看考勤创建的自定义代码,现在我已经对数据进行了硬编码,您可以调用服务而不是调用服务来获取动态数据。
app.component.ts
import { Component, OnInit, ElementRef, ViewEncapsulation, ViewChild } from '@angular/core';
import { DataSource } from '@angular/cdk';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
import { MdPaginator, MdSort } from '@angular/material';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/observable/merge';
import 'rxjs/add/operator/map';
declare let d3: any;
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
displayedColumns = ['shiftDate', 'swipeIn', 'swipeOut', 'duration', 'status'];
exampleDatabase = new ExampleDatabase();
dataSource: ExampleDataSource | null;
@ViewChild(MdPaginator) paginator: MdPaginator;
@ViewChild(MdSort) sort: MdSort;
ngOnInit() {
this.dataSource = new ExampleDataSource(this.exampleDatabase, this.paginator, this.sort);
}
}
export interface attendanceData {
shiftDate: string;
swipeIn: string;
swipeOut: string;
duration: string;
status: 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<attendanceData[]> = new BehaviorSubject<attendanceData[]>([]);
get data(): attendanceData[] {
let data = [
{
"shiftDate": "17-July-2017",
"swipeIn": "10:00 AM",
"swipeOut": "06:00 PM",
"duration": "8 Hours",
"status": "PRESENT"
},
{
"shiftDate": "16-July-2017",
"swipeIn": "9:00 AM",
"swipeOut": "5:00 AM",
"duration": "7 Hours",
"status": "PRESENT"
}
];
return data;
}
constructor() {
this.dataChange.next(this.data);
}
}
export class ExampleDataSource extends DataSource<any> {
_filterChange = new BehaviorSubject('');
get filter(): string { return this._filterChange.value; }
set filter(filter: string) { this._filterChange.next(filter); }
constructor(private _exampleDatabase: ExampleDatabase, private _paginator: MdPaginator, private _sort: MdSort) {
super();
}
/** Connect function called by the table to retrieve one stream containing the data to render. */
connect(): Observable<attendanceData[]> {
const displayDataChanges = [
this._exampleDatabase.dataChange,
this._paginator.page,
this._sort.mdSortChange
];
return Observable.merge(...displayDataChanges).map(() => {
// const data = this._exampleDatabase.data.slice();
const data = this.getSortedData();
// Grab the page's slice of data.
const startIndex = this._paginator.pageIndex * this._paginator.pageSize;
return data.splice(startIndex, this._paginator.pageSize);
});
}
disconnect() { }
getSortedData(): attendanceData[] {
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 'shiftDate': [propertyA, propertyB] = [a.shiftDate, b.shiftDate]; break;
case 'swipeIn': [propertyA, propertyB] = [a.swipeIn, b.swipeIn]; break;
case 'swipeOut': [propertyA, propertyB] = [a.swipeOut, b.swipeOut]; break;
case 'duration': [propertyA, propertyB] = [a.duration, b.duration]; break;
}
let valueA = isNaN(+propertyA) ? propertyA : +propertyA;
let valueB = isNaN(+propertyB) ? propertyB : +propertyB;
return (valueA < valueB ? -1 : 1) * (this._sort.direction == 'asc' ? 1 : -1);
});
}
}
app.component.html
<div class="example-container mat-elevation-z8">
<md-table #table [dataSource]="dataSource" mdSort>
<!--- Note that these columns can be defined in any order.
The actual rendered columns are set as a property on the row definition" -->
<!-- ID Column -->
<ng-container cdkColumnDef="shiftDate">
<md-header-cell *cdkHeaderCellDef md-sort-header> Shift Date </md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.shiftDate}} </md-cell>
</ng-container>
<!-- Progress Column -->
<ng-container cdkColumnDef="swipeIn">
<md-header-cell *cdkHeaderCellDef md-sort-header> Swipe In </md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.swipeIn}}% </md-cell>
</ng-container>
<!-- Name Column -->
<ng-container cdkColumnDef="swipeOut">
<md-header-cell *cdkHeaderCellDef> Swipe Out </md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.swipeOut}} </md-cell>
</ng-container>
<!-- Color Column -->
<ng-container cdkColumnDef="duration">
<md-header-cell *cdkHeaderCellDef>Duration</md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.duration}} </md-cell>
</ng-container>
<!-- Color Column -->
<ng-container cdkColumnDef="status">
<md-header-cell *cdkHeaderCellDef>Status</md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.status}} </md-cell>
</ng-container>
<md-header-row *cdkHeaderRowDef="displayedColumns"></md-header-row>
<md-row *cdkRowDef="let row; columns: displayedColumns;"></md-row>
</md-table>
<md-paginator #paginator
[length]="exampleDatabase.data.length"
[pageIndex]="0"
[pageSize]="25"
[pageSizeOptions]="[5, 10, 25, 100]">
</md-paginator>
</div>
app.module.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { MaterialModule, MdTableModule } from '@angular/material';
import { FlexLayoutModule } from '@angular/flex-layout';
import { CdkTableModule } from '@angular/cdk';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserAnimationsModule,
CdkTableModule,
BrowserModule,
MaterialModule, MdTableModule,
FlexLayoutModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
这是一篇由me.you 撰写的文章,您需要知道的都在这里。
https://medium.com/@fnote/md-tables-angular-material-be2c45947955
让我们通过 piece.you 获取代码片段,将在此处找到完整代码 https://material.angular.io/components/table/overview
import {Component} from '@angular/core';
import {DataSource} from '@angular/cdk';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/observable/merge';
import 'rxjs/add/operator/map';
导入您需要的必要软件包。确保在安装 angular material 时安装 angular cdk。
在继续之前,最好提及什么是数据源,什么是可观察的,什么是行为主题,还有 rxjs。
RXJS 是近来前端开发的热门话题。它是一个 javascript 反应式编程库(反应式编程只是构建软件应用程序的一种方式。本质上,你的软件被构建为“反应” 到使用 Observables 发生的变化(如点击事件、正在获取的数据等),以便更容易编写异步或 callback-based 代码。
导入 cdk 是因为 md-tables 建立在它之上。 cdk tables 是 md tables.
的基础
什么是可观察值?
Observables 能够随时间处理多个值的能力使它们成为处理 real-time 数据、事件和您能想到的任何类型的流的理想选择。
当处理来自流的 in-flow 个值时,Observables 提供了更好的控制。
Observable 是数据源的包装器,数据源是一个值流,随着时间的推移可能会发出多个值,我们希望在新值出现时做一些事情。
我们通过订阅连接观察者和可观察对象。订阅说有人在听这些价值流。
一个观察者订阅一个 Observable。 Observable 通过调用观察者的方法来发出项目或向其观察者发送通知。
observer 最多实现 3 methods.they 是 complete() ,next() 和 onerror()。
next() 方法将在新值 emitted.whenever observable 抛出错误时被 observable 调用将来它会调用 complete() 方法。
我强烈建议您关注 academind 在 youtube 上关于 RXJS 库的系列,以更深入地了解 RXJS 功能、观察者、可观察对象、主题、行为主题和订阅。
让我们继续代码
@Component({
selector: 'table-basic-example',
styleUrls: ['table-basic-example.css'],
templateUrl: 'table-basic-example.html',
})
这是常规的 angular 4.selector 是外部各方引用我们组件的名称。样式 Url 是我们的 /file 此组件引用的位置,用于样式目的和在模板 url.
中找到组件的基本 html
export class TableBasicExample {
displayedColumns = ['userId', 'userName', 'progress', 'color'];
exampleDatabase = new ExampleDatabase();
dataSource: ExampleDataSource | null;
ngOnInit() {
this.dataSource = new ExampleDataSource(this.exampleDatabase);
}
}
首先,我们将需要在浏览器上显示的 table 的所有列组成一个数组(列标题),该数组再次从 html 文件中引用。
并且我们进一步创建了一个示例数据库实例class和一个在开始时不携带数据的数据源实例。
然后将示例数据库中的数据注入此数据源以填充它,因为它最初是空的
Ng onitint 是一个生命周期钩子,由 angular 调用以标记组件创建完成。
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'];
我们有 2 个数组。它们填满了我们的示例数据库
export interface UserData {
id: string;
name: string;
progress: string;
color: string;
}
这里定义了一个接口。这里提到的变量最终会成为我们table的列。
export class ExampleDatabase {
dataChange: BehaviorSubject<UserData[]> = new BehaviorSubject<UserData[]>
([]);
get data(): UserData[] { return this.dataChange.value; }
constructor() {
// Fill up the database with 100 users.
for (let i = 0; i < 100; i++) { this.addUser(); }
}
addUser() {
const copiedData = this.data.slice();
copiedData.push(this.createNewUser());
this.dataChange.next(copiedData);
}
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))]
};
}
}
这是数据源用来检索 table 数据的示例数据库。您只定义了 2 个数组,但实际上要显示 4 列。您可以从数组中的数据中填充 2 列,但此处其他 2 列的数据必须在此 class.
中生成
那么什么是主题?
Observable 本身不能发出值,但我们希望能够自己发出。但是如果我们需要自己发出新值,我们必须使用一个主题。 Subject 是一个 observable,它继承自 observable,但我们可以手动调用它的 next() 方法,这样我们就可以触发一个新值的发射。因此 subject 是一个活跃的可观察对象。除了作为可观察对象之外,它还是一个观察者,因此除了订阅它之外,您还可以向主题发送值。
行为主体到底是什么?
行为主体是一种特殊的主体,但它与主体不同,它具有初始值。它需要一个初始值,因为它必须始终 return 一个订阅值,即使它没有收到 next()
Rx.subject()
订阅最初不会得到任何东西
Rx.behaviorsubject('a')
订阅最初获得“a”
不用担心用 const name 编写的代码......我们在名称数组中有大约 20 个名称,但我们需要 100 个不同的 names.So 这里我们以随机模式更改它们的首字母。
进度也是随机计算的。
数据变化是行为主体类型的变量。
this.dataChange.next(copiedData);
..每当新用户被推入数组时,数据更改就会通知订阅者。丁tachange 是一种 Stream,只要数据被修改就会发出。
创建一个名为 datachange 的变量,它是一个具有初始值数组的行为主题
制作一个名为复制数据的数组
创建一个具有 4 个属性的新用户。用户是像 objects 一样创建的,这 4 个属性是他们的属性。
添加新用户后调用下一个方法
在特殊的 observable 和 subject emits.add 上调用 next 方法 user() 将用户添加到数据库,而 create user 方法构建具有 4 个不同属性的用户 object。
数据源提供应该在 table 中呈现的数据。请注意,数据源可以以任何方式检索其数据。在这种情况下,数据源提供了对公共数据库 ExampleDatabase 的引用。数据源只获取数据并发送 table 应该呈现的内容,没有别的。
export class ExampleDataSource extends DataSource<any> {
constructor(private _exampleDatabase: ExampleDatabase) {
super();
}
connect(): Observable<UserData[]> {
return this._exampleDatabase.dataChange;
}
disconnect() {}
}
正在将 table 连接到数据源
数据通过数据源提供给 table。
Connect 函数将 collection 查看器(例如数据 table)连接到数据源。 table 调用 Connect 函数以获取包含应呈现的数据的流。必须为此连接函数提供参数。
当 table 接收到数据源时,它会调用 DataSource 的连接函数,该函数 return 是一个发出数据数组的可观察对象。
每当数据源向该流发送数据时,table 就会更新。
因为数据源提供了这个流,所以它承担了触发table更新的责任。这可以基于任何东西:网络套接字连接、用户交互、模型更新、time-based 间隔等。最常见的是,更新将由排序和分页等用户交互触发。
Disconnect 函数断开 table 和数据源之间的连接。
让我们看看 HTML 文件或我们的模板。
单元格模板
<ng-container cdkColumnDef="color">
<md-header-cell *cdkHeaderCellDef>Color</md-header-cell>
<md-cell *cdkCellDef="let row" [style.color]="row.color"> {{row.color}}
</md-cell>
</ng-container>
table 的第一列是 defined.with 指令 cdkColumnDef 每列都被赋予一个 name.this 是引用 table 中该特定列的名称从其他 places.each 列然后继续定义 header 单元格模板和数据单元格 template.header 单元格提供并显示列的名称,单元格模板检索应显示和显示的数据它们位于 header 行下方。
cdkCellDef 导出行上下文
tables header行和数据行定义如下
行模板如下,
<md-header-row *cdkHeaderRowDef="displayedColumns"></md-header-row>
<md-row *cdkRowDef="let row; columns: displayedColumns;"></md-row>
“显示的列”数组在您的 .ts(打字稿文件)中,颜色是列或数组的元素(根据我们的示例)。
这些行模板查看提供给 cdkColumnDef 的名称并找到要呈现的特定列。
cdkRowDef 还导出行上下文。行的呈现内容来自单元格模板而不是行模板。
如需进一步阅读,请查看此内容
Angular Material
编辑说明
material.angular.io
如何动态生成所需的列?
<ng-container *ngFor="let col of displayedColumns" cdkColumnDef= {{col}}>
<md-header-cell *cdkHeaderCellDef md-sort-header > {{ col }} </md-header-
cell>
<md-cell *cdkCellDef="let row"> {{row[col]}} </md-cell>
</ng-container>
将这段代码与上一段代码进行比较。这里我们循环遍历 displayedColumns 数组,并在此过程中分配列名,因此我们生成所需的列循环遍历数组,而不是手动定义所有需要的列HTML 文件。
至此我将结束这个解释,md tables 进一步为您提供分页、排序和过滤等功能。官方文档包含示例,您可以参考这些示例,以便将这些功能添加到您的 md table.
现在你知道 md 的幕后发生了什么了 table。
我在尝试使用这种方法时遇到了很多麻烦:
import { DataSource } from '@angular/cdk/collections';
.....
我可以得到 table,但是无法对列进行排序,因为排序不是已知的 属性 数据源,等等
最后我注意到正在使用 "@angular/material": "^5.0.0-rc0"
,
目前,我正在使用 MatTableDataSource
进口
import {MatTableDataSource} from '@angular/material';
CLASS 变量
private ELEMENT_DATA: reportInterface[] = [];
public tbDataSource;
public displayedColumns;
并且在构造函数
this.dataService.getReport().subscribe(results => {
if(!results)return;
this.ELEMENT_DATA = results;
this.displayedColumns = [.............];
this.tbDataSource = new MatTableDataSource(this.ELEMENT_DATA);
this.tbDataSource.sort = this.sort;
});
这是我的过滤函数
applyFilter(filterValue: string) {
this.tbDataSource.filter = filterValue;
}
我觉得这样更快更容易
我正在尝试实施 Material2 data table。但是我无法理解如何以正确的方式使用它。
import {Component, ElementRef, ViewChild} from '@angular/core';
import {DataSource} from '@angular/cdk';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/observable/merge';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/observable/fromEvent';
@Component({
selector: 'table-filtering-example',
styleUrls: ['table-filtering-example.css'],
templateUrl: 'table-filtering-example.html',
})
export class TableFilteringExample {
displayedColumns = ['userId', 'userName', 'progress', 'color'];
exampleDatabase = new ExampleDatabase();
dataSource: ExampleDataSource | null;
@ViewChild('filter') filter: ElementRef;
ngOnInit() {
this.dataSource = new ExampleDataSource(this.exampleDatabase);
Observable.fromEvent(this.filter.nativeElement, 'keyup')
.debounceTime(150)
.distinctUntilChanged()
.subscribe(() => {
if (!this.dataSource) { return; }
this.dataSource.filter = this.filter.nativeElement.value;
});
}
}
/** Constants used to fill up our data base. */
const COLORS = ['maroon', 'red', 'orange', 'yellow', 'olive', 'green', 'purple',
'fuchsia', 'lime', 'teal', 'aqua', 'blue', 'navy', 'black', 'gray'];
const NAMES = ['Maia', 'Asher', 'Olivia', 'Atticus', 'Amelia', 'Jack',
'Charlotte', 'Theodore', 'Isla', 'Oliver', 'Isabella', 'Jasper',
'Cora', 'Levi', 'Violet', 'Arthur', 'Mia', 'Thomas', 'Elizabeth'];
export interface UserData {
id: string;
name: string;
progress: string;
color: string;
}
/** An example database that the data source uses to retrieve data for the table. */
export class ExampleDatabase {
/** Stream that emits whenever the data has been modified. */
dataChange: BehaviorSubject<UserData[]> = new BehaviorSubject<UserData[]>([]);
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<any> {
_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<UserData[]> {
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() {}
}
上面是datatable的代码,让我很迷惑。甚至他们的文档也很差。有人可以解释一下上面代码的流程吗?
如果您觉得问题太基础,请忽略?
您示例中的代码是通用 table 的定义,使用 material2 规范中的新 cdk 组件。
你必须记住 md-table
是 cdk-table
的可视化实现,所以你需要声明一个 cdk,其模型与 HTML.[=40= 中的 md-model 兼容]
例如:
我声明一个 cdk-table
实现如下:
- 首先是依赖:
Material2中的新CDK组件,使用:
import { DataSource } from '@angular/cdk';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/observable/merge';
import 'rxjs/add/operator/map';
- TS中HTML的结构定义:
我定义了一个displayedColumns
数组,项目是我HTMLtable中的列,顺序是:
displayedColumns = ['userId', 'userName', 'progress'];
ExampleDatabase
类型的数据库(具有特定手动定义的对象):
exampleDatabase = new ExampleDatabase();
最后声明一个dataSource
,这是我数据的来源。是手动定义或数据为空的对象。
dataSource: ExampleDataSource | null;
在ngOnInit()
方法中,我简单地声明我的dataSource
是一个新的ExampleDataSource
,参数是我的exampleDataBase
.
很好,现在开始执行剩余的代码:
首先,为 DataBase
声明一个接口。这对于保持数据的一致性非常重要,数据库必须遵守定义的方案。
在这个例子中,数据库有三列:id、name 和 progress:
export interface UserData {
id: number;
name: string;
progress: string;
}
下一步是用我的DataBase
中的数据定义创建一个class(对象)ExampleDatabase
。您可以创建一个连接到实际数据库(PostgreSQL,MongoDB)的服务,获取真实数据并在另一种方法中为 cdk-datatable 创建对象,但是在这个例子中我们使用在 运行 时间模拟的内存数据库。
export class ExampleDatabase {
/** Stream that emits whenever the data has been modified. */
dataChange: BehaviorSubject<UserData[]> = new BehaviorSubject<UserData[]>([]);
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() {
return {
id: 1,
name: 'example',
progress: Math.round(Math.random() * 100).toString()
};
}
}
很好,我终于用 DataSource
.
export class ExampleDataSource extends DataSource<any> {
constructor(private _exampleDatabase: ExampleDatabase) {
super();
}
/** Connect function called by the table to retrieve one stream containing the data to render. */
connect(): Observable<UserData[]> {
return this._exampleDatabase.dataChange;
}
disconnect() { }
}
此方法确保数据格式正确,并将"connection"释放到DataBase
(在内存中)以获取其中的数据。
最后,在HTML中使用md-table
组件或cdk-table
组件。 md-table
组件使用material设计风格,cdk-table
使用通用风格..
md-table:
<div class="example-container mat-elevation-z8">
<md-table #table [dataSource]="dataSource">
<!-- ID Column -->
<ng-container cdkColumnDef="userId">
<md-header-cell *cdkHeaderCellDef> ID </md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.id}} </md-cell>
</ng-container>
<!-- Progress Column -->
<ng-container cdkColumnDef="progress">
<md-header-cell *cdkHeaderCellDef> Progress </md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.progress}}% </md-cell>
</ng-container>
<!-- Name Column -->
<ng-container cdkColumnDef="userName">
<md-header-cell *cdkHeaderCellDef> Name </md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.name}} </md-cell>
</ng-container>
<md-header-row *cdkHeaderRowDef="displayedColumns"></md-header-row>
<md-row *cdkRowDef="let row; columns: displayedColumns;"></md-row>
</md-table>
</div>
cdk-table:
<div class="example-container mat-elevation-z8">
<cdk-table #table [dataSource]="dataSource" class="example-table">
<!-- ID Column -->
<ng-container cdkColumnDef="userId">
<cdk-header-cell *cdkHeaderCellDef class="example-header-cell"> ID </cdk-header-cell>
<cdk-cell *cdkCellDef="let row" class="example-cell"> {{row.id}} </cdk-cell>
</ng-container>
<!-- Progress Column -->
<ng-container cdkColumnDef="progress">
<cdk-header-cell *cdkHeaderCellDef class="example-header-cell"> Progress </cdk-header-cell>
<cdk-cell *cdkCellDef="let row" class="example-cell"> {{row.progress}}% </cdk-cell>
</ng-container>
<!-- Name Column -->
<ng-container cdkColumnDef="userName">
<cdk-header-cell *cdkHeaderCellDef class="example-header-cell"> Name </cdk-header-cell>
<cdk-cell *cdkCellDef="let row" class="example-cell"> {{row.name}} </cdk-cell>
</ng-container>
<cdk-header-row *cdkHeaderRowDef="displayedColumns" class="example-header-row"></cdk-header-row>
<cdk-row *cdkRowDef="let row; columns: displayedColumns;" class="example-row"></cdk-row>
</cdk-table>
</div>
其余的实现、搜索、菜单、复选框等,由您负责实现处理信息的逻辑。
使用有关 cdk-table 的文档了解更多详情:
https://material.angular.io/guide/cdk-table
结果:
Do me saber and achievement,我理解我的解释,我为我的英语道歉。我在学习。
这是为观看考勤创建的自定义代码,现在我已经对数据进行了硬编码,您可以调用服务而不是调用服务来获取动态数据。
app.component.ts
import { Component, OnInit, ElementRef, ViewEncapsulation, ViewChild } from '@angular/core';
import { DataSource } from '@angular/cdk';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
import { MdPaginator, MdSort } from '@angular/material';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/observable/merge';
import 'rxjs/add/operator/map';
declare let d3: any;
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
displayedColumns = ['shiftDate', 'swipeIn', 'swipeOut', 'duration', 'status'];
exampleDatabase = new ExampleDatabase();
dataSource: ExampleDataSource | null;
@ViewChild(MdPaginator) paginator: MdPaginator;
@ViewChild(MdSort) sort: MdSort;
ngOnInit() {
this.dataSource = new ExampleDataSource(this.exampleDatabase, this.paginator, this.sort);
}
}
export interface attendanceData {
shiftDate: string;
swipeIn: string;
swipeOut: string;
duration: string;
status: 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<attendanceData[]> = new BehaviorSubject<attendanceData[]>([]);
get data(): attendanceData[] {
let data = [
{
"shiftDate": "17-July-2017",
"swipeIn": "10:00 AM",
"swipeOut": "06:00 PM",
"duration": "8 Hours",
"status": "PRESENT"
},
{
"shiftDate": "16-July-2017",
"swipeIn": "9:00 AM",
"swipeOut": "5:00 AM",
"duration": "7 Hours",
"status": "PRESENT"
}
];
return data;
}
constructor() {
this.dataChange.next(this.data);
}
}
export class ExampleDataSource extends DataSource<any> {
_filterChange = new BehaviorSubject('');
get filter(): string { return this._filterChange.value; }
set filter(filter: string) { this._filterChange.next(filter); }
constructor(private _exampleDatabase: ExampleDatabase, private _paginator: MdPaginator, private _sort: MdSort) {
super();
}
/** Connect function called by the table to retrieve one stream containing the data to render. */
connect(): Observable<attendanceData[]> {
const displayDataChanges = [
this._exampleDatabase.dataChange,
this._paginator.page,
this._sort.mdSortChange
];
return Observable.merge(...displayDataChanges).map(() => {
// const data = this._exampleDatabase.data.slice();
const data = this.getSortedData();
// Grab the page's slice of data.
const startIndex = this._paginator.pageIndex * this._paginator.pageSize;
return data.splice(startIndex, this._paginator.pageSize);
});
}
disconnect() { }
getSortedData(): attendanceData[] {
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 'shiftDate': [propertyA, propertyB] = [a.shiftDate, b.shiftDate]; break;
case 'swipeIn': [propertyA, propertyB] = [a.swipeIn, b.swipeIn]; break;
case 'swipeOut': [propertyA, propertyB] = [a.swipeOut, b.swipeOut]; break;
case 'duration': [propertyA, propertyB] = [a.duration, b.duration]; break;
}
let valueA = isNaN(+propertyA) ? propertyA : +propertyA;
let valueB = isNaN(+propertyB) ? propertyB : +propertyB;
return (valueA < valueB ? -1 : 1) * (this._sort.direction == 'asc' ? 1 : -1);
});
}
}
app.component.html
<div class="example-container mat-elevation-z8">
<md-table #table [dataSource]="dataSource" mdSort>
<!--- Note that these columns can be defined in any order.
The actual rendered columns are set as a property on the row definition" -->
<!-- ID Column -->
<ng-container cdkColumnDef="shiftDate">
<md-header-cell *cdkHeaderCellDef md-sort-header> Shift Date </md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.shiftDate}} </md-cell>
</ng-container>
<!-- Progress Column -->
<ng-container cdkColumnDef="swipeIn">
<md-header-cell *cdkHeaderCellDef md-sort-header> Swipe In </md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.swipeIn}}% </md-cell>
</ng-container>
<!-- Name Column -->
<ng-container cdkColumnDef="swipeOut">
<md-header-cell *cdkHeaderCellDef> Swipe Out </md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.swipeOut}} </md-cell>
</ng-container>
<!-- Color Column -->
<ng-container cdkColumnDef="duration">
<md-header-cell *cdkHeaderCellDef>Duration</md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.duration}} </md-cell>
</ng-container>
<!-- Color Column -->
<ng-container cdkColumnDef="status">
<md-header-cell *cdkHeaderCellDef>Status</md-header-cell>
<md-cell *cdkCellDef="let row"> {{row.status}} </md-cell>
</ng-container>
<md-header-row *cdkHeaderRowDef="displayedColumns"></md-header-row>
<md-row *cdkRowDef="let row; columns: displayedColumns;"></md-row>
</md-table>
<md-paginator #paginator
[length]="exampleDatabase.data.length"
[pageIndex]="0"
[pageSize]="25"
[pageSizeOptions]="[5, 10, 25, 100]">
</md-paginator>
</div>
app.module.ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { NgModule } from '@angular/core';
import { MaterialModule, MdTableModule } from '@angular/material';
import { FlexLayoutModule } from '@angular/flex-layout';
import { CdkTableModule } from '@angular/cdk';
import { AppComponent } from './app.component';
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserAnimationsModule,
CdkTableModule,
BrowserModule,
MaterialModule, MdTableModule,
FlexLayoutModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
这是一篇由me.you 撰写的文章,您需要知道的都在这里。 https://medium.com/@fnote/md-tables-angular-material-be2c45947955
让我们通过 piece.you 获取代码片段,将在此处找到完整代码 https://material.angular.io/components/table/overview
import {Component} from '@angular/core';
import {DataSource} from '@angular/cdk';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/startWith';
import 'rxjs/add/observable/merge';
import 'rxjs/add/operator/map';
导入您需要的必要软件包。确保在安装 angular material 时安装 angular cdk。 在继续之前,最好提及什么是数据源,什么是可观察的,什么是行为主题,还有 rxjs。
RXJS 是近来前端开发的热门话题。它是一个 javascript 反应式编程库(反应式编程只是构建软件应用程序的一种方式。本质上,你的软件被构建为“反应” 到使用 Observables 发生的变化(如点击事件、正在获取的数据等),以便更容易编写异步或 callback-based 代码。 导入 cdk 是因为 md-tables 建立在它之上。 cdk tables 是 md tables.
的基础什么是可观察值?
Observables 能够随时间处理多个值的能力使它们成为处理 real-time 数据、事件和您能想到的任何类型的流的理想选择。 当处理来自流的 in-flow 个值时,Observables 提供了更好的控制。 Observable 是数据源的包装器,数据源是一个值流,随着时间的推移可能会发出多个值,我们希望在新值出现时做一些事情。 我们通过订阅连接观察者和可观察对象。订阅说有人在听这些价值流。 一个观察者订阅一个 Observable。 Observable 通过调用观察者的方法来发出项目或向其观察者发送通知。 observer 最多实现 3 methods.they 是 complete() ,next() 和 onerror()。 next() 方法将在新值 emitted.whenever observable 抛出错误时被 observable 调用将来它会调用 complete() 方法。
我强烈建议您关注 academind 在 youtube 上关于 RXJS 库的系列,以更深入地了解 RXJS 功能、观察者、可观察对象、主题、行为主题和订阅。
让我们继续代码
@Component({
selector: 'table-basic-example',
styleUrls: ['table-basic-example.css'],
templateUrl: 'table-basic-example.html',
})
这是常规的 angular 4.selector 是外部各方引用我们组件的名称。样式 Url 是我们的 /file 此组件引用的位置,用于样式目的和在模板 url.
中找到组件的基本 htmlexport class TableBasicExample {
displayedColumns = ['userId', 'userName', 'progress', 'color'];
exampleDatabase = new ExampleDatabase();
dataSource: ExampleDataSource | null;
ngOnInit() {
this.dataSource = new ExampleDataSource(this.exampleDatabase);
}
}
首先,我们将需要在浏览器上显示的 table 的所有列组成一个数组(列标题),该数组再次从 html 文件中引用。
并且我们进一步创建了一个示例数据库实例class和一个在开始时不携带数据的数据源实例。 然后将示例数据库中的数据注入此数据源以填充它,因为它最初是空的 Ng onitint 是一个生命周期钩子,由 angular 调用以标记组件创建完成。
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'];
我们有 2 个数组。它们填满了我们的示例数据库
export interface UserData {
id: string;
name: string;
progress: string;
color: string;
}
这里定义了一个接口。这里提到的变量最终会成为我们table的列。
export class ExampleDatabase {
dataChange: BehaviorSubject<UserData[]> = new BehaviorSubject<UserData[]>
([]);
get data(): UserData[] { return this.dataChange.value; }
constructor() {
// Fill up the database with 100 users.
for (let i = 0; i < 100; i++) { this.addUser(); }
}
addUser() {
const copiedData = this.data.slice();
copiedData.push(this.createNewUser());
this.dataChange.next(copiedData);
}
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))]
};
}
}
这是数据源用来检索 table 数据的示例数据库。您只定义了 2 个数组,但实际上要显示 4 列。您可以从数组中的数据中填充 2 列,但此处其他 2 列的数据必须在此 class.
中生成那么什么是主题? Observable 本身不能发出值,但我们希望能够自己发出。但是如果我们需要自己发出新值,我们必须使用一个主题。 Subject 是一个 observable,它继承自 observable,但我们可以手动调用它的 next() 方法,这样我们就可以触发一个新值的发射。因此 subject 是一个活跃的可观察对象。除了作为可观察对象之外,它还是一个观察者,因此除了订阅它之外,您还可以向主题发送值。
行为主体到底是什么? 行为主体是一种特殊的主体,但它与主体不同,它具有初始值。它需要一个初始值,因为它必须始终 return 一个订阅值,即使它没有收到 next() Rx.subject() 订阅最初不会得到任何东西 Rx.behaviorsubject('a') 订阅最初获得“a”
不用担心用 const name 编写的代码......我们在名称数组中有大约 20 个名称,但我们需要 100 个不同的 names.So 这里我们以随机模式更改它们的首字母。
进度也是随机计算的。
数据变化是行为主体类型的变量。
this.dataChange.next(copiedData);
..每当新用户被推入数组时,数据更改就会通知订阅者。丁tachange 是一种 Stream,只要数据被修改就会发出。 创建一个名为 datachange 的变量,它是一个具有初始值数组的行为主题 制作一个名为复制数据的数组 创建一个具有 4 个属性的新用户。用户是像 objects 一样创建的,这 4 个属性是他们的属性。 添加新用户后调用下一个方法 在特殊的 observable 和 subject emits.add 上调用 next 方法 user() 将用户添加到数据库,而 create user 方法构建具有 4 个不同属性的用户 object。 数据源提供应该在 table 中呈现的数据。请注意,数据源可以以任何方式检索其数据。在这种情况下,数据源提供了对公共数据库 ExampleDatabase 的引用。数据源只获取数据并发送 table 应该呈现的内容,没有别的。
export class ExampleDataSource extends DataSource<any> {
constructor(private _exampleDatabase: ExampleDatabase) {
super();
}
connect(): Observable<UserData[]> {
return this._exampleDatabase.dataChange;
}
disconnect() {}
}
正在将 table 连接到数据源
数据通过数据源提供给 table。
Connect 函数将 collection 查看器(例如数据 table)连接到数据源。 table 调用 Connect 函数以获取包含应呈现的数据的流。必须为此连接函数提供参数。 当 table 接收到数据源时,它会调用 DataSource 的连接函数,该函数 return 是一个发出数据数组的可观察对象。 每当数据源向该流发送数据时,table 就会更新。 因为数据源提供了这个流,所以它承担了触发table更新的责任。这可以基于任何东西:网络套接字连接、用户交互、模型更新、time-based 间隔等。最常见的是,更新将由排序和分页等用户交互触发。 Disconnect 函数断开 table 和数据源之间的连接。 让我们看看 HTML 文件或我们的模板。 单元格模板
<ng-container cdkColumnDef="color">
<md-header-cell *cdkHeaderCellDef>Color</md-header-cell>
<md-cell *cdkCellDef="let row" [style.color]="row.color"> {{row.color}}
</md-cell>
</ng-container>
table 的第一列是 defined.with 指令 cdkColumnDef 每列都被赋予一个 name.this 是引用 table 中该特定列的名称从其他 places.each 列然后继续定义 header 单元格模板和数据单元格 template.header 单元格提供并显示列的名称,单元格模板检索应显示和显示的数据它们位于 header 行下方。 cdkCellDef 导出行上下文 tables header行和数据行定义如下 行模板如下,
<md-header-row *cdkHeaderRowDef="displayedColumns"></md-header-row>
<md-row *cdkRowDef="let row; columns: displayedColumns;"></md-row>
“显示的列”数组在您的 .ts(打字稿文件)中,颜色是列或数组的元素(根据我们的示例)。 这些行模板查看提供给 cdkColumnDef 的名称并找到要呈现的特定列。 cdkRowDef 还导出行上下文。行的呈现内容来自单元格模板而不是行模板。 如需进一步阅读,请查看此内容 Angular Material
编辑说明 material.angular.io 如何动态生成所需的列?
<ng-container *ngFor="let col of displayedColumns" cdkColumnDef= {{col}}>
<md-header-cell *cdkHeaderCellDef md-sort-header > {{ col }} </md-header-
cell>
<md-cell *cdkCellDef="let row"> {{row[col]}} </md-cell>
</ng-container>
将这段代码与上一段代码进行比较。这里我们循环遍历 displayedColumns 数组,并在此过程中分配列名,因此我们生成所需的列循环遍历数组,而不是手动定义所有需要的列HTML 文件。 至此我将结束这个解释,md tables 进一步为您提供分页、排序和过滤等功能。官方文档包含示例,您可以参考这些示例,以便将这些功能添加到您的 md table.
现在你知道 md 的幕后发生了什么了 table。
我在尝试使用这种方法时遇到了很多麻烦:
import { DataSource } from '@angular/cdk/collections';
.....
我可以得到 table,但是无法对列进行排序,因为排序不是已知的 属性 数据源,等等
最后我注意到正在使用 "@angular/material": "^5.0.0-rc0"
,
目前,我正在使用 MatTableDataSource
进口
import {MatTableDataSource} from '@angular/material';
CLASS 变量
private ELEMENT_DATA: reportInterface[] = [];
public tbDataSource;
public displayedColumns;
并且在构造函数
this.dataService.getReport().subscribe(results => {
if(!results)return;
this.ELEMENT_DATA = results;
this.displayedColumns = [.............];
this.tbDataSource = new MatTableDataSource(this.ELEMENT_DATA);
this.tbDataSource.sort = this.sort;
});
这是我的过滤函数
applyFilter(filterValue: string) {
this.tbDataSource.filter = filterValue;
}
我觉得这样更快更容易