Glauco Todesco
Glauco Todesco

Reputation: 15

Angular Material @ViewChield MatTable: How to update table?

I have a child component that uses MatTable. I need to update the table after edit or create using renderRows(); The table datasource is an @Input(). I have tried onChanges, but I got undefined because of @ViewChild.

Where do I have to put renderRows() to update the table when products[] is updated? In this case, the table is updated, but with an undefined error message.

Child Component:

  //Table datasource
  @Input()
  products: Product[] = [];


  @ViewChild(MatTable)
  table !: MatTable<Product>;

  ngOnChanges(){
    this.table.renderRows(); //works but I got undefined
  }


In the parent component, when the state changes:

   this.productService.saveProduct(product).subscribe({
          next: data => {
            this.products.push(data);
          }
    });

If I instead reload and create a new array, it works perfect, but I don't want to call my rest api:

 loadProducts() {
    this.productService.getProducts().subscribe({
      next: data => { this.products = data }
    });
  }
this.productService.saveProduct(product).subscribe({
          next: data => {
                this.loadProducts()        
          }
});

Upvotes: 0

Views: 1488

Answers (2)

Glauco Todesco
Glauco Todesco

Reputation: 15

Potencial solution 1:

Now I dont have undefined and the the works perfect, but repeat twice the same line looks wrong for me.

  ngAfterViewInit() {
    this.dataSource =  new MatTableDataSource(this.products);;
    this.table.renderRows();
  }

  ngOnChanges(){
    this.dataSource = new MatTableDataSource(this.products);
  }

Potencial solution 2:

Parent component always creates a new array when something changes:

this.productService.saveProduct(product).subscribe({
          next: data => {
            this.products.push(data);
            this.products = Array.from(this.products);
          }
        });

Upvotes: 0

Chris Hamilton
Chris Hamilton

Reputation: 10954

Simply check that the table is defined before calling the function

@ViewChild(MatTable)
  table?: MatTable<Product>;

  ngOnChanges(){
    if (table) this.table.renderRows(); //works but I got undefined
  }

! means that the variable is always defined, which in this case is not true. Use ? in these situations and the compiler will help you avoid these types of bugs.

I see that you are hoping ngOnChanges will fire when you change the array Products. This is not the case as change detection will only check object identity, not value. You can call ngOnChanges directly, reassign the array after pushing, or simply create an update function - up to you.

   this.productService.saveProduct(product).subscribe({
          next: data => {
            this.products.push(data);
            this.ngOnChanges();
          }
    });

or

   this.productService.saveProduct(product).subscribe({
          next: data => {
            this.products.push(data);
            this.products = this.products.slice();
          }
    });

or

  renderRows(){
    this.table?.renderRows();
  }

  this.productService.saveProduct(product).subscribe({
          next: data => {
            this.products.push(data);
            this.renderRows();
          }
  });

Upvotes: 1

Related Questions