我正在使用一个垫子表列出用户选择的语言的内容。他们还可以使用对话框面板添加新的语言。在他们添加了一门语言并返回之后。我希望刷新数据源以显示他们所做的更改。

我通过从服务获取用户数据并在刷新方法中将其传递到数据源来初始化数据存储。

Language.component.ts

import { Component, OnInit } from '@angular/core';
import { LanguageModel, LANGUAGE_DATA } from '../../../../models/language.model';
import { LanguageAddComponent } from './language-add/language-add.component';
import { AuthService } from '../../../../services/auth.service';
import { LanguageDataSource } from './language-data-source';
import { LevelbarComponent } from '../../../../directives/levelbar/levelbar.component';
import { DataSource } from '@angular/cdk/collections';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
import { MatSnackBar, MatDialog } from '@angular/material';

@Component({
  selector: 'app-language',
  templateUrl: './language.component.html',
  styleUrls: ['./language.component.scss']
})
export class LanguageComponent implements OnInit {

  displayedColumns = ['name', 'native', 'code', 'level'];
  teachDS: any;
  user: any;

  constructor(private authService: AuthService, private dialog: MatDialog) { }

  ngOnInit() {
    this.refresh();
  }

  add() {
    this.dialog.open(LanguageAddComponent, {
      data: { user: this.user },
    }).afterClosed().subscribe(result => {
      this.refresh();
    });
  }

  refresh() {
    this.authService.getAuthenticatedUser().subscribe((res) => {
      this.user = res;
      this.teachDS = new LanguageDataSource(this.user.profile.languages.teach);   
    });
  }
}

language-data-source.ts

import {MatPaginator, MatSort} from '@angular/material';
import {DataSource} from '@angular/cdk/collections';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/observable/merge';
import 'rxjs/add/operator/map';

export class LanguageDataSource extends DataSource<any> {

  constructor(private languages) {
    super();
  }

  connect(): Observable<any> {
    return Observable.of(this.languages);
  }

  disconnect() {
    // No-op
  }

}

因此,我尝试调用一个刷新方法,我从后端再次获得用户,然后重新初始化数据源。然而,这并没有起作用,没有发生任何变化。


当前回答

在Angular 9中,秘密是this.dataSource.data = this.dataSource.data;

例子:

import { MatTableDataSource } from '@angular/material/table';

dataSource: MatTableDataSource<MyObject>;

refresh(): void {
    this.applySomeModif();
    // Do what you want with dataSource

    this.dataSource.data = this.dataSource.data;
}

applySomeModif(): void {
    // add some data
    this.dataSource.data.push(new MyObject());
    // delete index number 4
    this.dataSource.data.splice(4, 0);
}

其他回答

做到这一点的最佳方法是向Datasource实现中添加一个额外的可观察对象。

在connect方法中,你应该已经使用了Observable。合并以订阅包含分页器的可观察对象数组。页面中,排序。sortChange等等。您可以添加一个新的主题,并在需要引起刷新时调用它。

就像这样:

export class LanguageDataSource extends DataSource<any> {

    recordChange$ = new Subject();

    constructor(private languages) {
      super();
    }

    connect(): Observable<any> {

      const changes = [
        this.recordChange$
      ];

      return Observable.merge(...changes)
        .switchMap(() => return Observable.of(this.languages));
    }

    disconnect() {
      // No-op
    }
}

然后可以调用recordChange$.next()来启动刷新。

当然,我会将调用包装在refresh()方法中,并将其从组件中的数据源实例w/中调用,以及其他适当的技术。

有两种方法可以做到这一点,因为Angular Material是不一致的,而且这一点的文档非常少。当新行到达时,Angular的材质表不会更新。令人惊讶的是,它被告知是因为性能问题。但这看起来更像是一个设计问题,他们无法改变。当出现新行时,表应该进行更新。如果默认情况下不应该启用这种行为,应该有一个开关来关闭它。

不管怎样,我们不能改变Angular Material。但我们基本上可以用一种记录很差的方法来做到这一点:

一,如果你直接使用数组作为源:

call table.renderRows()

mat-table的ViewChild在哪里

第二-如果你使用排序和其他功能

table.renderRows()令人惊讶地不会工作。因为这里的垫子和桌子不一致。你需要使用黑客来告诉源代码改变了。你可以用这个方法:

this.dataSource.data = yourDataSource;

其中dataSource是用于排序和其他功能的MatTableDataSource包装器。

所以对我来说,没有人能给出和@Kay一样好的答案。对我来说,这是关于排序,排序表不发生变化垫。 我的目的是这个答案,因为这是我通过搜索谷歌找到的唯一主题。 我使用的是Angular 6。

正如这里所说:

由于表对性能进行了优化,因此它不会自动检查数据数组的更改。相反,当在数据数组上添加、删除或移动对象时,您可以通过调用其renderRows()方法来触发对表所呈现行的更新。

所以你只需要在你的refresh()方法中调用renderRows()来显示你的更改。

请参见这里的积分。

在Angular 9中,秘密是this.dataSource.data = this.dataSource.data;

例子:

import { MatTableDataSource } from '@angular/material/table';

dataSource: MatTableDataSource<MyObject>;

refresh(): void {
    this.applySomeModif();
    // Do what you want with dataSource

    this.dataSource.data = this.dataSource.data;
}

applySomeModif(): void {
    // add some data
    this.dataSource.data.push(new MyObject());
    // delete index number 4
    this.dataSource.data.splice(4, 0);
}

好吧,我遇到了一个类似的问题,我向数据源添加了一些东西,但它没有重新加载。

我发现最简单的方法就是重新分配数据

let dataSource = ['a','b','c']
dataSource.push('d')
let cloned = dataSource.slice()
// OR IN ES6 // let cloned = [...dataSource]
dataSource = cloned