如何使用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-tablecdk-table 的可视化实现,所以你需要声明一个 cdk,其模型与 HTML.[=40= 中的 md-model 兼容]

例如:

我声明一个 cdk-table 实现如下:

  1. 首先是依赖:

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';
  1. 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;
}

我觉得这样更快更容易