Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

primeng - How do I update Angular UI with OnPush strategy without changing the @Input reference?

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

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

1 Reply

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...