Angular + Material - How to refresh a data source

2020-01-27 10:40发布

I am using a mat-table to list the content of the users chosen languages. They can also add new languages using dialog panel. After they added a language and returned back. I want my datasource to refresh to show the changes they made.

I initialize the datastore by getting user data from a service and passing that into a datasource in the refresh method.

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
  }

}

So I have tried to call a refresh method where I get the user from the backend again and then I reinitialize the data source. However this does not work, no changes are occurring.

20条回答
我欲成王,谁敢阻挡
2楼-- · 2020-01-27 11:05
import { Subject } from 'rxjs/Subject';
import { Observable } from 'rxjs/Observable';

export class LanguageComponent implemnts OnInit {
  displayedColumns = ['name', 'native', 'code', 'leavel'];
  user: any;
  private update = new Subject<void>();
  update$ = this.update.asObservable();

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

   ngOnInit() {
     this.update$.subscribe(() => { this.refresh()});
   }

   setUpdate() {
     this.update.next();
   }

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

 refresh() {
   this.authService.getAuthenticatedUser().subscribe((res) => {
     this.user = res;
     this.teachDS = new LanguageDataSource(this.user.profile.languages.teach);   
    });
  }
}
查看更多
Bombasti
3楼-- · 2020-01-27 11:05

After reading Material Table not updating post data update #11638 Bug Report I found the best (read, the easiest solution) was as suggested by the final commentor 'shhdharmen' with a suggestion to use an EventEmitter.

This involves a few simple changes to the generated datasource class

ie) add a new private variable to your datasource class

import { EventEmitter } from '@angular/core';
...
private tableDataUpdated = new EventEmitter<any>();

and where I push new data to the internal array (this.data), I emit an event.

public addRow(row:myRowInterface) {
    this.data.push(row);
    this.tableDataUpdated.emit();
}

and finally, change the 'dataMutation' array in the 'connect' method - as follows

const dataMutations = [
    this.tableDataUpdated,
    this.paginator.page,
    this.sort.sortChange
];
查看更多
登录 后发表回答