Home > Net >  Angular Mat-table DataSource value changed while updating the status
Angular Mat-table DataSource value changed while updating the status

Time:10-30

table -> Action -> InActive

When we have changed the row status value, the mat-table data source value is also updated.

Our requirement is to change the status value after being updated to the database but now the mat-table immediately changes the status value.

How do we stop the mat-table Datasource update?

I have given the example. please see the stackblitz

HTML

<table mat-table [dataSource]="dataSource" >
  <!--- Note that these columns can be defined in any order.
        The actual rendered columns are set as a property on the row definition" -->

  <!-- Position Column -->
  <ng-container matColumnDef="position">
    <th mat-header-cell *matHeaderCellDef>No.</th>
    <td mat-cell *matCellDef="let element">{{element.position}}</td>
  </ng-container>

  <!-- Name Column -->
  <ng-container matColumnDef="name">
    <th mat-header-cell *matHeaderCellDef>Name</th>
    <td mat-cell *matCellDef="let element">{{element.name}}</td>
  </ng-container>

  <!-- Weight Column -->
  <ng-container matColumnDef="weight">
    <th mat-header-cell *matHeaderCellDef>Weight</th>
    <td mat-cell *matCellDef="let element">{{element.weight}}</td>
  </ng-container>

  <!-- Symbol Column -->
  <ng-container matColumnDef="symbol">
    <th mat-header-cell *matHeaderCellDef>Symbol</th>
    <td mat-cell *matCellDef="let element">{{element.symbol}}</td>
  </ng-container>
  <ng-container matColumnDef="status">
    <th mat-header-cell *matHeaderCellDef>status</th>
    <td mat-cell *matCellDef="let element">{{element.status}}</td>
  </ng-container>
  <ng-container matColumnDef="actions">
    <th mat-header-cell *matHeaderCellDef>Actions</th>
    <td mat-cell *matCellDef="let element">
      <button
        mat-button
        [matMenuTriggerFor]="menu"
        
      >
        Acción
      </button>
      <mat-menu #menu="matMenu">
        <button
          mat-menu-item
          
          (click)="updateStatus('inActive',element)"
        >
          <span>InActive</span>
        </button>
      </mat-menu>
    </td>
  </ng-container>
  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

ts

import { Component } from '@angular/core';

/**
 * @title Basic use of `<table mat-table>`
 */
@Component({
  selector: 'table-basic-example',
  styleUrls: ['table-basic-example.css'],
  templateUrl: 'table-basic-example.html',
})
export class TableBasicExample {
  displayedColumns = [
    'position',
    'name',
    'weight',
    'symbol',
    'status',
    'actions',
  ];
  dataSource = ELEMENT_DATA;
  updateStatus(status, item) {
    console.log('before set status', this.dataSource);
    item.status = status;
    console.log('After set status', this.dataSource);
  }
}

export interface PeriodicElement {
  name: string;
  position: number;
  weight: number;
  symbol: string;
  status: string;
}

const ELEMENT_DATA: PeriodicElement[] = [
  {
    position: 1,
    name: 'Hydrogen',
    weight: 1.0079,
    symbol: 'H',
    status: 'Active',
  },
  {
    position: 2,
    name: 'Helium',
    weight: 4.0026,
    symbol: 'He',
    status: 'Active',
  },
  {
    position: 3,
    name: 'Lithium',
    weight: 6.941,
    symbol: 'Li',
    status: 'Active',
  },
];

stackblitz demo: https://stackblitz.com/edit/angular-keucik?file=app/table-basic-example.ts

CodePudding user response:

The problem is that when you modify element, you are modifying the source code of your table. (datasource)

You will not be able to edit the value of an item, without modifying the table. But you can create an auxiliary array, to keep your new states.

Example

TS

import { Component } from '@angular/core';
import { MatTableDataSource } from '@angular/material';

/**
 * @title Basic use of `<table mat-table>`
 */
@Component({
  selector: 'table-basic-example',
  styleUrls: ['table-basic-example.css'],
  templateUrl: 'table-basic-example.html',
})
export class TableBasicExample {
  displayedColumns = [
    'position',
    'name',
    'weight',
    'symbol',
    'status',
    'actions',
  ];
  dataSource = ELEMENT_DATA;
  dataSourceAux = JSON.parse(JSON.stringify(ELEMENT_DATA));

  updateStatus(status, item) {
    const idx = this.dataSourceAux.findIndex((x) => x.name === item.name);
    this.dataSourceAux[idx].status = status;
    /**
     * or const itemAux = this.dataSourceAux.find((x) => x.name === item.name)
     * itemAux.status = status;
     *
     * Now you have two list, one with the real table values, and another with the copy of them
     * And what you should do, is change the value of the auxiliar list, not the real.
     * when you want to update the table, just do
     * this.dataSource = JSON.parse(JSON.stringify(this.dataSourceAux))
     */
  }
}

export interface PeriodicElement {
  name: string;
  position: number;
  weight: number;
  symbol: string;
  status: string;
}

/**  Copyright 2018 Google Inc. All Rights Reserved.
    Use of this source code is governed by an MIT-style license that
    can be found in the LICENSE file at http://angular.io/license */

const ELEMENT_DATA: PeriodicElement[] = [
  {
    position: 1,
    name: 'Hydrogen',
    weight: 1.0079,
    symbol: 'H',
    status: 'Active',
  },
  {
    position: 2,
    name: 'Helium',
    weight: 4.0026,
    symbol: 'He',
    status: 'Active',
  },
  {
    position: 3,
    name: 'Lithium',
    weight: 6.941,
    symbol: 'Li',
    status: 'Active',
  },
];

The code, it could be better and safely. But it's just an example.

  • Related