Angular + Material - Comment rafraîchir une Source de données (mat-table)

j'utilise un tapis de table pour lister le contenu des utilisateurs des langues choisies. Ils peuvent également ajouter de nouvelles langues en utilisant le panneau de dialogue. Après ils ont ajouté une langue et retourné. Je veux que ma source de données pour actualiser pour afficher les modifications apportées.

j'initialise le datastore en récupérant les données utilisateur d'un service et en les passant dans une source de données dans la mise à jour méthode.

Langue.composant.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);   
    });
  }
}

langue-source de données.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
  }

}

J'ai donc essayé d'appeler une méthode de rafraîchissement où j'obtiens l'utilisateur de l'arrière-plan à nouveau et puis je réinitialise la source de données. Toutefois, cela ne fonctionne pas, aucun changement ne se produit.

23
demandé sur HDJEMAI 2017-10-14 19:10:09

6 réponses

déclenchez une détection de changement en utilisant ChangeDetectorRef dans le refresh() méthode juste après avoir reçu les nouvelles données, injecter ChangeDetectorRef dans le constructeur et l'utilisation detectChanges comme ceci:

import { Component, OnInit, ChangeDetectorRef } 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, private changeDetectorRefs: ChangeDetectorRef) { }

  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);
      this.changeDetectorRefs.detectChanges();
    });
  }
}
20
répondu HDJEMAI 2018-09-16 17:37:34

je ne sais pas si le ChangeDetectorRef a été requise lorsque la question a été créé, mais maintenant c'est assez:

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

// ...

dataSource = new MatTableDataSource<MyDataType>();

refresh() {
  this.myService.doSomething().subscribe(data: MyDataType[] => {
    this.dataSource.data = data;
  }
}
12
répondu MA-Maddin 2018-03-12 08:57:17

puisque vous utilisez MatPaginator, vous avez juste besoin de faire n'importe quel changement à paginator, cela déclenche le rechargement des données.

astuce:

this.paginator._changePageSize(this.paginator.pageSize); 

cette mise à jour de la taille de la page à la taille de la page actuelle, donc essentiellement rien ne change, sauf le privé _emitPageEvent() la fonction s'appelle aussi, déclenchant la recharge de la table.

6
répondu takeshin 2018-04-22 15:56:54

la meilleure façon de le faire est d'ajouter un observable supplémentaire à votre implémentation Datasource.

dans la méthode connect vous devriez déjà utiliser Observable.merge pour souscrire à un tableau d'observables qui inclut le paginateur.page, trier.sortChange, etc. Vous pouvez ajouter un nouveau sujet à ceci et l'appeler ensuite quand vous avez besoin de provoquer un rafraîchissement.

quelque chose comme ceci:

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
    }
}

Et puis vous pouvez appeler recordChange$.next() pour initier un rafraîchir.

naturellement j'envelopperais l'appel dans une méthode refresh() et l'annulerais de l'instance datasource w/dans le component, et d'autres techniques appropriées.

4
répondu jogi 2018-02-03 12:37:37

ceci.dataSource = new MatTableDataSource (this.éléments);

ajouter cette ligne sous votre action d'ajouter ou supprimer la ligne particulière.

refresh() {
  this.authService.getAuthenticatedUser().subscribe((res) => {
    this.user = new MatTableDataSource<Element>(res);   
  });
}
4
répondu Pooja Paigude 2018-05-25 13:33:14
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);   
    });
  }
}
1
répondu Machhindra Neupane 2018-08-05 15:05:11