1

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 Answer 1

4

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.