Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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
  }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
894 views
Welcome To Ask or Share your Answers For Others

1 Answer

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">
...

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...