Loui
Loui

Reputation: 550

Error observed on console, while using angular mat table

I am using angular along with angular material to create a mat table. Everything works fine. Its just that I see an error in console which I not able to figure out how to rectify it. Again I see my data loaded, pagination works, but I do observe an error on console which I don't want. How can I correct this.

Error on console : enter image description here

MessageDataTableDataSource.ts

import { DataSource } from '@angular/cdk/collections';
import { MatPaginator, MatSort } from '@angular/material';
import { map } from 'rxjs/operators';
import { Observable, of as observableOf, merge } from 'rxjs';
import { MessageData } from '../../data-model/MessageData';

export class MessageDataTableDataSource extends DataSource<MessageData> {

  constructor(private paginator: MatPaginator, 
    private sort: MatSort, private data: MessageData[]) {
      super();
  }

  connect(): Observable<MessageData[]> {
    const dataMutations = [
      observableOf(this.data),
      this.paginator.page,
      this.sort.sortChange
    ];

    this.paginator.length = this.data.length;

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

  disconnect() {}

  private getPagedData(data: MessageData[]) {
    const startIndex = this.paginator.pageIndex * this.paginator.pageSize;
    return data.splice(startIndex, this.paginator.pageSize);
  }

  private getSortedData(data: MessageData[]) {
    if (!this.sort.active || this.sort.direction === '') {
      return data;
    }

    return data.sort((a, b) => {
      const isAsc = this.sort.direction === 'asc';
      switch (this.sort.active) {
        case 'id': return compare(+a.Message.Id, +b.Message.Id, isAsc);
        default: return 0;
      }
    });
  }
}

function compare(a, b, isAsc) {
  return (a < b ? -1 : 1) * (isAsc ? 1 : -1);
}

HTML Template

<div class="mat-elevation-z8">
    <table mat-table #table [dataSource]="dataSource" matSort aria-label="Elements">
        <!-- Id Column -->
        <ng-container matColumnDef="id">
            <th mat-header-cell *matHeaderCellDef mat-sort-header>Id</th>
            <td mat-cell *matCellDef="let row">{{row.message.id}}</td>
        </ng-container>

        <!-- Message Text Column -->
        <ng-container matColumnDef="messageText">
            <th mat-header-cell *matHeaderCellDef mat-header>Message Text</th>
            <td mat-cell *matCellDef="let row">{{row.message.messageText}}</td>
        </ng-container>

        <!-- Delivery Date -->
        <ng-container matColumnDef="deliveryDate">
            <th mat-header-cell *matHeaderCellDef mat-header>Delivery Date</th>
            <td mat-cell *matCellDef="let row">{{row.message.deliveryDateTime}}</td>
        </ng-container>

        <!-- Status Column -->
        <ng-container matColumnDef="status">
            <th mat-header-cell *matHeaderCellDef mat-header>Status</th>
            <td mat-cell *matCellDef="let row">{{row.message.messageStatus}}</td>
        </ng-container>

        <!-- Action Column -->
        <ng-container matColumnDef="action">
            <th mat-header-cell *matHeaderCellDef mat-header>Action</th>
            <td mat-cell *matCellDef="let row">
                <button type="button" class="btn btn-danger"
                [disabled]="row.message.messageStatus != 'PENDING'" 
                (click)="cancelScheduledMessage()">Cancel</button>
            </td>
        </ng-container>

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

    <mat-paginator #paginator
        [length]="dataSource.data.length" 
        [pageIndex]="0"
        [pageSize]="5"
        [pageSizeOptions]="[5, 10, 50, 100]">
    </mat-paginator>
</div>

MessageListComponent.ts

import { Component, OnInit, ViewChild } from '@angular/core';
import { MatSort, MatPaginator } from '@angular/material';
import { MessageDataTableDataSource } from './message-data-table-datasource';
import { MessageService } from '../message.service';
import { MessageData } from '../../data-model/MessageData';

@Component({
  selector: 'app-message-list',
  templateUrl: './message-list.component.html',
  styleUrls: ['./message-list.component.css']
})
export class MessageListComponent implements OnInit {

  @ViewChild(MatPaginator) paginator: MatPaginator;
  @ViewChild(MatSort) sort: MatSort;
  dataSource: MessageDataTableDataSource;
  displayedColumns = ['id', 'messageText', 'deliveryDate', 'status', 'action'];

  constructor(private messageService: MessageService) { }

  ngOnInit() {
    this.messageService.getMessages().subscribe(
      (messageData: MessageData[]) => {
        this.dataSource = new MessageDataTableDataSource(this.paginator,
           this.sort, messageData);
      },
      (error) => console.log(error)
    );
  }

}

Looking forward to kind suggestions. Thanks

Upvotes: 0

Views: 575

Answers (1)

Sajeetharan
Sajeetharan

Reputation: 222552

You can handle this error by using *ngIf OR safe navigation operator (?) .

Reason: It's just a console error that occurs when you try to access the datasource in the template before the actual value is set on the component. this happens because the data is assigned asynchronously.

Solution:

<mat-paginator #paginator
        [length]="dataSource?.data?.length" 
        [pageIndex]="0"
        [pageSize]="5"
        [pageSizeOptions]="[5, 10, 50, 100]">
</mat-paginator>

Upvotes: 1

Related Questions