Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Updating Angular Material Table data and columns with ngrx and trackby does not refresh the DOM

I've got that Angular Material Table :

<table mat-table [dataSource]="data" [trackBy]="trackBy">
  <ng-container
    [matColumnDef]="column.value"
    *ngFor="let column of columns; let i = index"
  >
    <th mat-header-cell *matHeaderCellDef>{{ column.label }}</th>
    <td mat-cell *matCellDef="let element">
      <input
        matInput
        [value]="element[column.value].value"
        type="text"
        (input)="updatedFn($event.target.value)"
      />
    </td>
  </ng-container>

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

And this ts file :

  
  @Component({
    ...
    changeDetection: ChangeDetectionStrategy.OnPush,
  })
  export class StuffComponent implements OnInit, OnChanges {
    @Input() data!: Data[];
    @Input() columns!: Column[];
  
    @Output() updated = new EventEmitter<Updated>();
  
    columnsToDisplay!: string[];
  
    constructor(private cdr: ChangeDetectorRef) {}
  
    trackBy(index: number) {
      return index;
    }
  
    ngOnChanges() {
      this.cdr.markForCheck();
    }
  
    ngOnInit() {
      this.columnsToDisplay = this._columns.map((item: Column) => item.value);
    }
  
    updatedFn(value: string) {
      this.updated.emit(value);
    }
  
  }
  

I added the trackBy because I was losing focus on input whenever I'm typing. Now with trackBy, I can freely type, it dispatches the action, then I use the reducer to make the changes to the state, then it correctly send back the fresh data to the table component : the @Input() data/colums are corrects. However, it does not update the DOM. I assume this is because of the trackBy, but if I use something like this :

 trackBy(index: number, stuff) {
      return stuff.value;
    }

...it loses focus again on the input.

Also, I tried to use this.cdr.markForCheck() but it did not do anything.

How can I update the DOM despite the trackyBy?

Edit: to be more precise on how I know it does not update the DOM -> in my reducer, I change the data value of another table cell but it does not appear on the table despite the @Input data contains the fresh data.

like image 721
GreatHawkeye Avatar asked Oct 19 '25 10:10

GreatHawkeye


1 Answers

I found a solution: I added the same trackyBy to the ngFor itself :

<ng-container [matColumnDef]="column.value" *ngFor="let column of columns; let i = index; trackBy: trackBy"

I also removed the ngOnChanges and markForCheck()

like image 126
GreatHawkeye Avatar answered Oct 22 '25 04:10

GreatHawkeye