1
votes

get quite stuck trying to set the datasource for the angular material table.

this is what i'm trying to do:

export class ServersTableDataSource extends DataSource<Server> {
  data: Server[] = EXAMPLE_DATA;

  constructor(private paginator: MatPaginator, private sort: MatSort, private serversService: ServersService) {
    super();
    this.data = this.serversService.getServers();
  }
  connect(): Observable<Server[]> {
    const dataMutations = [
      observableOf(this.data),
      this.paginator.page,
      this.sort.sortChange
    ];

    // Set the paginators length
    this.paginator.length = this.data.length;

    return merge(...dataMutations).pipe(map(() => {
      return this.getPagedData(this.getSortedData([...this.data]));
    }));
  }


export class ServersTableComponent implements OnInit {

  constructor(private serversService: ServersService) { }

  ngOnInit() {
    this.dataSource = new ServersTableDataSource(this.paginator, this.sort, this.serversService);
    this.serversService.serversChanges.subscribe(() => {
      this.dataSource.data = this.serversService.getServers();
    });
    //done this way because for unknown reason if i return an observable,
    //it doesn't pass a value. Anyway, this isn't relevant. The point is that this.dataSource.data  is set.
  }

In this example, despite that there is observableOf(this.data) in connect method, the this.dataSource.data changes do not apply.

The only way i was able to make it work is to re-initialize datasource on each change, which doesn't feel right (table is updated from websocket data very frequently).

  ngOnInit() {
    this.dataSource = new ServersTableDataSource(this.paginator, this.sort, this.serversService);
    this.serversService.serversChanges.subscribe(() => {
      this.dataSource = new ServersTableDataSource(this.paginator, this.sort, this.serversService);
    });
  }
1

1 Answers

4
votes

The solution was to implement a different updating mechanism with BehaviorSubject and track the rows by index (for some reason wasn't able to make it work with tracking by unique obj sub-properties.)

datasource:

export class ServersTableDataSource extends DataSource<Server> {
  data: Server[] = [];

  constructor(private paginator: MatPaginator, private sort: MatSort, private serversService: ServersService) {
    super();
  }


  connect(): Observable<Server[]> {
    return new Observable<Server[]>(observer => {
      this.serversService.getServersSubj().subscribe((servers) => {
        if (servers) {
          return this.applyMutations(servers).subscribe(data => {
            observer.next(data);
          });
        }
      });
    });
  }

  disconnect() {

  }

  applyMutations(tmpData: Server[]): Observable<Server[]> {
    const dataMutations = [
      observableOf(tmpData),
      this.paginator.page,
      this.sort.sortChange
    ];

    // Set the paginators length
    this.paginator.length = this.data.length;

    return merge(...dataMutations).pipe(map(() => {
      return this.getPagedData(this.getSortedData([...tmpData]));
    }));
  }

tracking changes:

  <mat-table #table [dataSource]="dataSource"
         [trackBy]="trackByIndex"
         multiTemplateDataRows
         matSort
         aria-label="Elements">

  ***in component:***

  trackByIndex(index, item) {
    return index;
  }

this.serversService.getServersSubj() returns BehaviorSubject.