Home > Net >  Angular re-render only changed row in a table with ngrx
Angular re-render only changed row in a table with ngrx

Time:10-30

I am using NGRX to load data from remote api, into an array, and after render the array in a classic HTML table. Partially the code looks like this:

  ngOnInit() {
    this.store
      .select(
        createSelector(
          (state: AppState) => state.userProperties,
          (propObject: UserProperties) => propObject
        )
      )
      .pipe(takeUntil(this.destroyed$))
      .subscribe(({properties, total }) => {
        this.propertyList = properties;
        this.totalFound = total;
      })

And render code:

      <tbody>
        <ng-container *ngFor="let row of propertyList">
          <tr>
            <td>
            </td>
            <td >{{ row.id }}</td>
            <td >{{ categoryLabels[row.category] | _: trans.lang }}</td>
            <td >{{ contractLabels[row.contract_type] | _: trans.lang }}</td>
            <td >{{ row.price }}</td>
            <td >{{ row.city }}</td>
            <td >
            </td>
            <td>
              <div >
                <button (click)="editProperty(row.id)" >
                  <edit-icon></edit-icon>
                </button>
                <button *ngIf="row.deleted === 0" (click)="archiveProperty(row.id)" title="Delete this property"
                  >
                  <img src="/assets/images/icons/delete-red.svg" />
                </button>
                <button (click)="toggleExpand(row.id)" >
                  <expand-icon [expanded]="expandedElements[row.id]"></expand-icon>
                </button>
              </div>
            </td>
          </tr>
        </ng-container>

The issue I notice if that if I change a row, example I click setStatus, which changes a row of the array, all the table renders again (causing some flickering).

Is there a way to tell angular to render only the rows of the array which have changed?

Solution (thanks to @Dmytro Demyanenko): Add trackBy to the ngFor:

<ng-container *ngFor="let row of propertyList; trackBy: trackByFn">

And define trackBy function:

  trackByFn(index, row) {
    return JSON.stringify(row);
  }

Angular will re-render the ngFor loop element only if the trackBy function returns a different value from the last one returned. In my case some data in the row might change and then I need to re-render.

CodePudding user response:

Yes, you can do this. You can use trackBy for ngFor. This is the way to tell angular to render only the rows of the array which have changed.

Please, read more about this here How to use trackBy with ngFor or here to see an example Explain ngFor trackBy in Angular

  • Related