【问题标题】:Angular Material Table | Add Remove rows at runtime角料表 |在运行时添加删除行
【发布时间】:2018-03-08 12:20:37
【问题描述】:

我正在使用由普通数组支持的Angular Material Table 作为数据源。

this.employees = this.route.snapshot.data.employes; // of type Employee[] resolved using a Resolve guard
this.dataSource = new MatTableDataSource<Employee>(this.employees);

最初呈现后,我想通过使用组件中的方法修改“this.employess”数组来从数据表中添加/删除行:-

addEmployee(e: Employee){
 this.employess.push(e);   // I expect the table to have one row added after this.
}

removeEmployee(index : number){
  // splice the array at given index & remove one row from data table
}

问题

当我在数组中添加删除元素时,数据表行不受影响。 我发现了一个blog 阐述了同样的问题,但使用了自定义数据源。有没有办法使用普通数组?

【问题讨论】:

  • Angular 不会检测对象(包括数组)上的更改,因为数组引用在添加或删除元素时不会更改。

标签: angular angular-material


【解决方案1】:

最简单的方法是在您的数据源上调用 _updateChangeSubscription(),因为您已经在使用 MatTableDataSource

this.dataSource = new MatTableDataSource(this.employees);

您修改后的新 addEmployee 方法将变为:

addEmployee(e: Employee){
 this.employess.push(e);   // I expect the table to have one row added after this.
 this.dataSource._updateChangeSubscription()  // THIS WILL DO
}

【讨论】:

  • 这对我有用。虽然我直接通过this.datasource.data 访问了 mat 数据源,而不是使用自己的数组来托管数据。我通过调用this.datasource.data.push() 推送到该列表
【解决方案2】:

在最新版本的 Angular Material 7/8

推送新行数据后需要调用.renderRows()方法

addRowData(row_obj){
   var d = new Date();
   this.dataSource.push({
     id:d.getTime(),
     name:row_obj.name
   });
   this.table.renderRows();
 }

 deleteRowData(row_obj){
    this.dataSource = this.dataSource.filter((value,key)=>{
      return value.id != row_obj.id;
    });
 }

源码教程link

【讨论】:

  • 如果我尝试将 this.dataSource.push 与 Angular 7 和最新材料一起使用,我会收到错误 - 我需要使用 this.dataSource.data.push
【解决方案3】:

问题是 angular/ Mat-table 在实例化后没有检测到对底层数组的任何修改。因此,如果您选择添加或删除一行,您必须显式地让表监听事件或只刷新表数据。以下是您的操作方法。

addEmployee(e: Employee){
 this.employess.push(e);   // I expect the table to have one row added after this.
 this.dataSource.data = this.employees; // this step will refresh the table
}

您的 remove 方法也是如此。

希望这会有所帮助。

【讨论】:

    【解决方案4】:

    您可以创建一个 EmployeeDataSource 类,它采用 Observable&lt;Employee[]&gt; 而不是 Employee[]

    import {DataSource} from '@angular/cdk/collections';
    import {Observable} from 'rxjs/Observable';
    
    export class EmployeeListDataSource extends DataSource<any> {
    
    
        constructor(private _employeeList$: Observable<Employee[]>) {
            super();
        }
    
        connect(): Observable<Employee[]> {
            return this._employeeList$;
        }
    
        disconnect() {
        }
    }
    

    然后通过传递一个 observable 创建你的数据源:

    this.dataSource = new EmployeeListDataSource(yourObservable);
    

    You can find a stackblitz example here.

    【讨论】:

      【解决方案5】:

      我不确定这是否是最佳解决方案,但您可以创建一个主题来存储您的数据。现在您可以像使用博文一样使用它了。

      public $data: BehaviorSubject<MyDataType[]> = new BehaviorSubject([]);
      
      addEmployee(e: Employee){
          this.$data
            .first()
            .subscribe(data => {
                let newData = data.slice();
                newData.push(e);
                this.$data.next(newData);
            }
      }
      

      【讨论】:

      • 对于行为主题,如果要访问它的当前值,则无需订阅,只需使用$data.value。虽然我记得这在某处被标记为反模式。
      【解决方案6】:

      我正在使用 Angular 9,这是我所做的

      this.dataSource.data.push({
            profile:"profile",
            skillRequired:"skillRequired"
          });
      this.dataSource.filter = "";
      

      使用过滤器数据表会自动更新

      【讨论】:

        猜你喜欢
        • 2012-02-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-23
        • 2022-11-18
        • 2012-11-27
        • 2011-03-28
        相关资源
        最近更新 更多