Winkel + Material - So aktualisieren Sie eine Datenquelle (Mat-Tabelle)


118

Ich verwende eine Mat-Tabelle, um den Inhalt der vom Benutzer ausgewählten Sprachen aufzulisten. Sie können auch neue Sprachen über das Dialogfeld hinzufügen. Nachdem sie eine Sprache hinzugefügt und zurückgekehrt waren. Ich möchte, dass meine Datenquelle aktualisiert wird, um die vorgenommenen Änderungen anzuzeigen.

Ich initialisiere den Datenspeicher, indem ich Benutzerdaten von einem Dienst abrufe und diese in der Aktualisierungsmethode an eine Datenquelle übergebe.

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
  }

}

Daher habe ich versucht, eine Aktualisierungsmethode aufzurufen, bei der der Benutzer erneut aus dem Backend abgerufen und dann die Datenquelle neu initialisiert wird. Dies funktioniert jedoch nicht, es treten keine Änderungen auf.


1
Wenn Sie die Änderung "aus der Datenquelle" auslösen möchten, schauen Sie bitte auf stackoverflow.com/questions/47897694/…
Yennefer

In diesem Fall können Ereignisemitter verwendet werden. stackoverflow.com/a/44858648/8300620
Rohit Parte

Antworten:


57

Lösen Sie eine Änderungserkennung aus, indem Sie ChangeDetectorRefdie refresh()Methode direkt nach dem Empfang der neuen Daten verwenden, ChangeDetectorRef in den Konstruktor einfügen und detectChanges wie folgt verwenden :

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();
    });
  }
}

9
Das scheint zu funktionieren, ist das der richtige Weg, es zu tun? Scheint ein bisschen hacky ...
Kay

Was sind die anderen Möglichkeiten? Können Sie in Ihrer Lösung Beispiele für eine vollständige Antwort angeben?
Kay


87

Ich weiß nicht, ob das ChangeDetectorReferforderlich war, als die Frage erstellt wurde, aber jetzt ist dies genug:

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

// ...

dataSource = new MatTableDataSource<MyDataType>();

refresh() {
  this.myService.doSomething().subscribe((data: MyDataType[]) => {
    this.dataSource.data = data;
  }
}

Beispiel:
StackBlitz


4
Während diese Lösung tatsächlich funktioniert, bringt sie den Materialpaginator durcheinander, wenn das Element an einer anderen Stelle als auf der ersten Ergebnisseite hinzugefügt wird. Ich verstehe, dass dies den Rahmen dieser Frage sprengt, aber haben Sie zufällig eine schnelle Lösung für dieses Problem, die Sie Ihrer Antwort hinzufügen könnten, da die beiden verwandt sind?
Knight

5
@Knight Ich denke, Sie müssen den Paginator der MatTableDataSource.paginatorEigenschaft zuweisen, nachdem die Ansicht des Paginators initialisiert wurde. Siehe die Beschreibung der paginatorEigenschaft hier: material.angular.io/components/table/api#MatTableDataSource
Martin Schneider

Gute Referenz. Ich hatte das noch nie in den Dokumenten gesehen. Vielen Dank!
Ritter

2
@ MA-Maddin Kannst du genauer sagen, wie es geht? Beispiel?
Nathanphan

@ Nathanphan spät, aber ein Beispiel hinzugefügt;)
Martin Schneider

46

Für mich gab niemand die gute Antwort auf das Problem, das ich getroffen habe und das fast das gleiche ist wie @Kay. Für mich geht es um das Sortieren, Sortiertabellen treten keine Änderungen in der Matte auf. Ich beabsichtige diese Antwort, da es das einzige Thema ist, das ich bei der Suche in Google finde. Ich benutze Angular 6.

Wie hier gesagt :

Da die Tabelle hinsichtlich der Leistung optimiert wird, wird nicht automatisch nach Änderungen am Datenarray gesucht. Wenn Objekte zum Datenarray hinzugefügt, entfernt oder verschoben werden, können Sie stattdessen eine Aktualisierung der gerenderten Zeilen der Tabelle auslösen, indem Sie die Methode renderRows () aufrufen.

So müssen Sie nur noch rufen renderRows () in der refresh () Methode , um Ihre Änderungen angezeigt werden.

Siehe hier für die Integration.


1
Wenn die Tabellendatenquelle auf dem Client geändert wird, ist diese Antwort wahrscheinlich das, wonach Sie suchen. Funktioniert super!
Alvin Saldanha

Dies ist die richtige Antwort ab Winkelmaterial 8
Tom

Danke dir. Aber von welchem ​​Objekt soll ich die "renderRows ()" aufrufen? Ist es in 'this.datasource'?
WitnessTruth

19

Da Sie verwenden MatPaginator, müssen Sie nur Änderungen am Paginator vornehmen. Dies löst ein erneutes Laden der Daten aus.

Einfacher Trick:

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

Dadurch wird die Seitengröße auf die aktuelle Seitengröße aktualisiert, sodass sich im Grunde nichts ändert, außer dass auch die private _emitPageEvent()Funktion aufgerufen wird, wodurch das erneute Laden der Tabelle ausgelöst wird.


Ich habe Ihren Code ausprobiert und er funktioniert nicht (hat keine Auswirkung). Allerdings funktioniert nextPage und dann previousPage wieder, ist aber keine Lösung.
Ahmed Hasn.

_changePageSize()ist nicht öffentlich richtig? Ist es sicher zu bedienen? Mehr auf stackoverflow.com/questions/59093781/…
Jones

9
this.dataSource = new MatTableDataSource<Element>(this.elements);

Fügen Sie diese Zeile unterhalb Ihrer Aktion zum Hinzufügen oder Löschen der jeweiligen Zeile hinzu.

refresh() {
  this.authService.getAuthenticatedUser().subscribe((res) => {
    this.user = new MatTableDataSource<Element>(res);   
  });
}

Was ist das? Elemente
Parvat

8

Der beste Weg, dies zu tun, besteht darin, Ihrer Datenquellenimplementierung ein zusätzliches Observable hinzuzufügen.

In der Connect-Methode sollten Sie bereits Observable.mergeein Array von Observables abonnieren, zu denen paginator.page, sort.sortChange usw. gehören. Sie können diesem einen neuen Betreff hinzufügen und ihn als Nächstes aufrufen, wenn Sie eine Aktualisierung veranlassen müssen.

etwas wie das:

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

Und dann können Sie anrufen recordChange$.next(), um eine Aktualisierung zu starten.

Natürlich würde ich den Aufruf in eine refresh () -Methode einschließen und ihn von der Datenquelleninstanz w / in der Komponente und anderen geeigneten Techniken abrufen.


Diese Methode kann der richtige Weg sein. Es funktioniert gut für mich
Manu

Wie implementiere ich dies, wenn ich MatTableDataSource erweitern möchte? Wenn ich Ihr Codebeispiel versuche, erhalte ich den FehlerProperty 'connect' in type 'customDataSource<T>' is not assignable to the same property in base type 'MatTableDataSource<T>'. Type '() => Observable<any>' is not assignable to type '() => BehaviorSubject<T[]>'. Type 'Observable<any>' is not assignable to type 'BehaviorSubject<T[]>'. Property '_value' is missing in type 'Observable<any>'.
Maurice

1
@Maurice Der Typ MatTableDataSource implementiert die Verbindungsmethode mit einem anderen Rückgabetyp. Es verwendet BehaviorSubject <t []>, was bedeutet, dass Sie nur das Beispiel ändern müssen, um dies anstelle eines Observable zurückzugeben. Sie sollten weiterhin in der Lage sein, DataSource zu verwenden. Wenn Sie jedoch MatTableDataSource verwenden müssen, geben Sie ein BehaviorSubject zurück, das Ihre Observable abonniert hat, vorausgesetzt, Sie haben eines, mit dem Sie beginnen können. Hoffentlich hilft das. Die genaue Syntax des neuen Datenquellentyps finden Sie in der Quelle für MatTableDataSource: github.com/angular/material2/blob/master/src/lib/table/…
jogi

7

Sie können einfach die Datenquellen-Verbindungsfunktion verwenden

this.datasource.connect().next(data);

wie so. 'Daten' sind die neuen Werte für die Datentabelle


Hatte Potenzial, scheint aber nicht zu funktionieren. Wenn Sie danach auf this.datasource.data zugreifen, wird es nicht aktualisiert.
Rui Marques

4

Sie können die Daten der Tabelle einfach mit "concat" aktualisieren:

beispielsweise:

language.component.ts

teachDS: any[] = [];

language.component.html

<table mat-table [dataSource]="teachDS" class="list">

Und wenn Sie die Daten aktualisieren (language.component.ts):

addItem() {
    // newItem is the object added to the list using a form or other way
    this.teachDS = this.teachDS.concat([newItem]);
 }

Wenn Sie "concat" eckig verwenden, erkennen Sie die Änderungen des Objekts (this.teachDS) und Sie müssen nichts anderes verwenden.

PD: Es funktioniert für mich in Winkel 6 und 7, ich habe keine andere Version ausprobiert.


2
Ja, es funktioniert bei mir, ist ein Problem mit der Referenz und dem Wert var, die Änderungserkennung sieht die neuen Änderungen nicht, dafür müssen Sie sie aktualisieren.
Mayra Rodriguez

Dies funktioniert möglicherweise, wenn die dataSource nur ein Array ist, nicht jedoch, wenn dataSource ein MatTableDataSource-Objekt ist.
Rui Marques


3

Nun, ich bin auf ein ähnliches Problem gestoßen, bei dem ich der Datenquelle etwas hinzugefügt habe und es nicht neu geladen wird.

Der einfachste Weg, den ich gefunden habe, war einfach, die Daten neu zuzuweisen

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

Perfekt!! Es wokrs !! Danke :)
Nicolas

3

In Angular 9 ist das Geheimnis this.dataSource.data = this.dataSource.data;

Beispiel:

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

2

Ich habe mit zwei Ressourcen eine gute Lösung erzielt:

Aktualisieren von dataSource und paginator:

this.dataSource.data = this.users;
this.dataSource.connect().next(this.users);
this.paginator._changePageSize(this.paginator.pageSize);

Hier wird beispielsweise dataSource definiert:

    users: User[];
    ...
    dataSource = new MatTableDataSource(this.users);
    ...
    this.dataSource.paginator = this.paginator;
    ...

1
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);   
    });
  }
}

8
Bitte fügen Sie Ihrer Antwort eine Erklärung hinzu. Nur der Postleitzahl ist nicht sehr hilfreich und kann dazu führen, dass Ihre Antwort entfernt wird.
TJ Wolschon

1

In meinem Fall (Angular 6+) habe ich geerbt MatTableDataSource, um zu erstellen MyDataSource. Ohne Aufruf nachthis.data = someArray

this.entitiesSubject.next(this.data as T[])

Daten wurden nicht angezeigt

Klasse MyDataSource

export class MyDataSource<T extends WhateverYouWant> extends MatTableDataSource<T> {

    private entitiesSubject = new BehaviorSubject<T[]>([]);


    loadDataSourceData(someArray: T[]){
        this.data = someArray //whenever it comes from an API asyncronously or not
        this.entitiesSubject.next(this.data as T[])// Otherwise data not displayed
    }

    public connect(): BehaviorSubject<T[]> {
        return this.entitiesSubject
    }

}//end Class 

1

Es gibt zwei Möglichkeiten, dies zu tun, da Angular Material inkonsistent ist und dies sehr schlecht dokumentiert ist. Die Winkelmaterialtabelle wird nicht aktualisiert, wenn eine neue Zeile eintrifft. Überraschenderweise wird gesagt, dass es an Leistungsproblemen liegt. Aber es sieht eher nach einem Designproblem aus, sie können sich nicht ändern. Es sollte erwartet werden, dass die Tabelle aktualisiert wird, wenn eine neue Zeile auftritt. Wenn dieses Verhalten nicht standardmäßig aktiviert sein soll, sollte es einen Schalter zum Ausschalten geben.

Auf jeden Fall können wir Angular Material nicht ändern. Grundsätzlich können wir jedoch eine sehr schlecht dokumentierte Methode verwenden:

Eins - wenn Sie ein Array direkt als Quelle verwenden:

call table.renderRows()

Dabei ist table ViewChild der Mat-Tabelle

Zweitens - wenn Sie Sortierung und andere Funktionen verwenden

table.renderRows () funktioniert überraschenderweise nicht. Weil mat-table hier inkonsistent ist. Sie müssen einen Hack verwenden, um die geänderte Quelle mitzuteilen. Sie machen es mit dieser Methode:

this.dataSource.data = yourDataSource;

Dabei ist dataSource der MatTableDataSource-Wrapper, der zum Sortieren und für andere Funktionen verwendet wird.


0

Das hat bei mir funktioniert:

refreshTableSorce() {
    this.dataSource = new MatTableDataSource<Element>(this.newSource);
}

Keine ideale Lösung, da die Quelle für die Tabelle neu erstellt wird. Die Verwendung dieser Lösung mit Streamlined / Socket ist nicht effizient.
Maihan Nijat

0

Ich denke, das MatTableDataSourceObjekt ist in irgendeiner Weise mit dem Datenarray verknüpft, das Sie an den MatTableDataSourceKonstruktor übergeben.

Zum Beispiel:

dataTable: string[];
tableDS: MatTableDataSource<string>;

ngOnInit(){
   // here your pass dataTable to the dataSource
   this.tableDS = new MatTableDataSource(this.dataTable); 
}

Also, wenn Sie Daten ändern müssen; Ändern Sie in der ursprünglichen Liste dataTableund spiegeln Sie dann die Änderung in der Tabelle durch die _updateChangeSubscription()Aufrufmethode ein tableDS.

Zum Beispiel:

this.dataTable.push('testing');
this.tableDS._updateChangeSubscription();

Das ist Arbeit mit mir durch Angular 6.


4
Dieser Methode wird ein Unterstrich vorangestellt _und Sie nennen es?
Stephane

0

Das funktioniert bei mir:

dataSource = new MatTableDataSource<Dict>([]);
    public search() {
        let url = `${Constants.API.COMMON}/dicts?page=${this.page.number}&` + 
        (this.name == '' ? '' : `name_like=${this.name}`);
    this._http.get<Dict>(url).subscribe((data)=> {
    // this.dataSource = data['_embedded'].dicts;
    this.dataSource.data =  data['_embedded'].dicts;
    this.page = data['page'];
    this.resetSelection();
  });
}

Daher sollten Sie Ihre Datenquelleninstanz als deklarieren MatTableDataSource


0

Ich habe weitere Nachforschungen angestellt und diesen Ort gefunden, um mir das zu geben, was ich brauchte - fühlt sich sauber an und bezieht sich auf Aktualisierungsdaten, wenn diese vom Server aktualisiert werden: https://blog.angular-university.io/angular-material-data-table/

Die meisten Credits auf der obigen Seite. Im Folgenden finden Sie ein Beispiel dafür, wie ein Mattenselektor verwendet werden kann, um eine Mattentabelle zu aktualisieren, die bei Änderung der Auswahl an eine Datenquelle gebunden ist. Ich verwende Angular 7. Es tut mir leid, dass ich umfangreich bin und versuche, vollständig, aber präzise zu sein. Ich habe so viele nicht benötigte Teile wie möglich herausgerissen. In der Hoffnung, jemand anderem zu helfen, schneller voranzukommen!

organisation.model.ts:

export class Organization {
    id: number;
    name: String;
}

organisation.service.ts:

import { Observable, empty } from 'rxjs';
import { of } from 'rxjs';

import { Organization } from './organization.model';

export class OrganizationService {
  getConstantOrganizations(filter: String): Observable<Organization[]> {
    if (filter === "All") {
      let Organizations: Organization[] = [
        { id: 1234, name: 'Some data' }
      ];
      return of(Organizations);
     } else {
       let Organizations: Organization[] = [
         { id: 5678, name: 'Some other data' }
       ];
     return of(Organizations);
  }

  // ...just a sample, other filterings would go here - and of course data instead fetched from server.
}

organisationdatasource.model.ts:

import { CollectionViewer, DataSource } from '@angular/cdk/collections';
import { Observable, BehaviorSubject, of } from 'rxjs';
import { catchError, finalize } from "rxjs/operators";

import { OrganizationService } from './organization.service';
import { Organization } from './organization.model';

export class OrganizationDataSource extends DataSource<Organization> {
  private organizationsSubject = new BehaviorSubject<Organization[]>([]);

  private loadingSubject = new BehaviorSubject<boolean>(false);

  public loading$ = this.loadingSubject.asObservable();

  constructor(private organizationService: OrganizationService, ) {
    super();
  }

  loadOrganizations(filter: String) {
    this.loadingSubject.next(true);

    return this.organizationService.getOrganizations(filter).pipe(
      catchError(() => of([])),
      finalize(() => this.loadingSubject.next(false))
    ).subscribe(organization => this.organizationsSubject.next(organization));
  }

  connect(collectionViewer: CollectionViewer): Observable<Organization[]> {
    return this.organizationsSubject.asObservable();
  }

  disconnect(collectionViewer: CollectionViewer): void {
    this.organizationsSubject.complete();
    this.loadingSubject.complete();
  }
}

organisations.component.html:

<div class="spinner-container" *ngIf="organizationDataSource.loading$ | async">
    <mat-spinner></mat-spinner>
</div>

<div>
  <form [formGroup]="formGroup">
    <mat-form-field fxAuto>
      <div fxLayout="row">
        <mat-select formControlName="organizationSelectionControl" (selectionChange)="updateOrganizationSelection()">
          <mat-option *ngFor="let organizationSelectionAlternative of organizationSelectionAlternatives"
            [value]="organizationSelectionAlternative">
            {{organizationSelectionAlternative.name}}
          </mat-option>
        </mat-select>
      </div>
    </mat-form-field>
  </form>
</div>

<mat-table fxLayout="column" [dataSource]="organizationDataSource">
  <ng-container matColumnDef="name">
    <mat-header-cell *matHeaderCellDef>Name</mat-header-cell>
    <mat-cell *matCellDef="let organization">{{organization.name}}</mat-cell>
  </ng-container>

  <ng-container matColumnDef="number">
    <mat-header-cell *matHeaderCellDef>Number</mat-header-cell>
    <mat-cell *matCellDef="let organization">{{organization.number}}</mat-cell>
  </ng-container>

  <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
  <mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
</mat-table>

organisations.component.scss:

.spinner-container {
    height: 360px;
    width: 390px;
    position: fixed;
}

organisation.component.ts:

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder } from '@angular/forms';
import { Observable } from 'rxjs';

import { OrganizationService } from './organization.service';
import { Organization } from './organization.model';
import { OrganizationDataSource } from './organizationdatasource.model';

@Component({
  selector: 'organizations',
  templateUrl: './organizations.component.html',
  styleUrls: ['./organizations.component.scss']
})
export class OrganizationsComponent implements OnInit {
  public displayedColumns: string[];
  public organizationDataSource: OrganizationDataSource;
  public formGroup: FormGroup;

  public organizationSelectionAlternatives = [{
    id: 1,
    name: 'All'
  }, {
    id: 2,
    name: 'With organization update requests'
  }, {
    id: 3,
    name: 'With contact update requests'
  }, {
    id: 4,
    name: 'With order requests'
  }]

  constructor(
    private formBuilder: FormBuilder,
    private organizationService: OrganizationService) { }

  ngOnInit() {
    this.formGroup = this.formBuilder.group({
      'organizationSelectionControl': []
    })

    const toSelect = this.organizationSelectionAlternatives.find(c => c.id == 1);
    this.formGroup.get('organizationSelectionControl').setValue(toSelect);

    this.organizationDataSource = new OrganizationDataSource(this.organizationService);
    this.displayedColumns = ['name', 'number' ];
    this.updateOrganizationSelection();
  }

  updateOrganizationSelection() {
    this.organizationDataSource.loadOrganizations(this.formGroup.get('organizationSelectionControl').value.name);
  }
}

0

Nachdem ich die Materialtabelle gelesen hatte, die nach der Aktualisierung der Daten nicht aktualisiert wurde # 11638 Fehlerbericht Ich fand die beste (gelesene, einfachste Lösung), wie vom letzten Kommentator 'shhdharmen' mit einem Vorschlag zur Verwendung eines EventEmitter vorgeschlagen.

Dies beinhaltet einige einfache Änderungen an der generierten Datenquellenklasse

dh) fügen Sie Ihrer Datenquellenklasse eine neue private Variable hinzu

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

und wo ich neue Daten in das interne Array (this.data) schiebe, gebe ich ein Ereignis aus.

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

und schließlich ändern Sie das Array 'dataMutation' in der Methode 'connect' wie folgt

const dataMutations = [
    this.tableDataUpdated,
    this.paginator.page,
    this.sort.sortChange
];

0

// das ist die dataSource
this.guests = [];

this.guests.push ({id: 1, name: 'Ricardo'});

// aktualisiere die dataSource this.guests = Array.from (this.guest);


0
npm install @matheo/datasource

Ich habe eine Bibliothek veröffentlicht, die in Zukunft die offizielle Material DataSource sein soll und jede Art von Eingabestreams (Sortieren, Paginieren, Filtern) und einige Konfigurationen mit Debugging unterstützt, um zu sehen, wie es beim Codieren funktioniert.

import { MatDataSourceModule } from '@matheo/datasource';

Die StackBlitz-Demo und weitere Informationen finden Sie hier:
https://medium.com/@matheo/reactive-datasource-for-angular-1d869b0155f6

Ich würde mich freuen, Ihre Meinung zu hören und Ihre Anwendungsfälle bei Bedarf zu unterstützen.
Viel Spaß beim Codieren!


-1

Ich hatte ChangeDetectorRef, Subject und BehaviourSubject ausprobiert, aber was funktioniert für mich?

dataSource = [];
this.dataSource = [];
 setTimeout(() =>{
     this.dataSource = this.tableData[data];
 },200)

was ist denn hier los? Ich habe das Gefühl, dass Fehler bei der Benennung von Variablen gemacht wurden.
ChumiestBucket
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.