0

I have a concrete component which extends an abstract class with one @Input() data. The one @Input data is used by a PrimeNG table to display rows. The PrimeNG table uses an Angular OnPush strategy.

When I push an object to the @Input data array, the change is not reflected in the UI.

If I change the reference of data after pushing an object to the array (via something like this.data = deepCopy(this.data) as Field[]), then the change is displayed in the UI.

In this case, I do not wish to change the reference of data as other components may manipulate that data and I do not wish to synchronize multiple different copies of the same data.

How can I force Angular to update the UI without changing the reference? ChangeDetectorRef.detectChanges() does not update the UI accordingly.

Abstract table class with PrimeNG table:

@Directive()
export abstract class TableComponent<T> implements OnChanges {

  @Input() data: T[];

  @ViewChild('dt') dataTable: Table; // PrimeNG table which displays rows of data

  ...
}

Concrete class with addRow() function:

@Component({
  selector: 'app-table',
  templateUrl: '...',
  styleUrls: ['...']
})
export class SomeComponent extends TableComponent<Field> implements OnInit, OnChanges {

  ...

  public addRow(): void {
    const field = {} as Field;
    field.id = 1;
    
    this.data.push(field);

    // this.changeDetectorRef.detectChanges(); // Does not update the UI
    // this.data = deepCopy(this.data) as Field[]; // Updates the UI by changing reference
  }
}

1 Answer 1

1

I figured out a solution that causes the UI to update correctly.

Binding PrimeNG table value property to a function which returns all of the expected data resolves the issue of the UI not updating.

public addRow(): void {
    const field = {} as Field;
    field.id = 1;
    
    this.data.push(field);
}

public getData(): Field[] {
    return this.data.filter(field => field.id > 0);
}

Component template snippet:

<p-table #dt [columns]="cols"
             [value]="getData()"
             [paginator]="true"
             [paginatorPosition]="'both'"
             [rows]="10">
...
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.