【问题标题】:Bugged PrimEng datatable change detection after upgrade Angular to 4将 Angular 升级到 4 后错误的 PrimEng 数据表更改检测
【发布时间】:2018-10-04 00:02:22
【问题描述】:

在我从 Angular 2 升级到 Angular 4 之后,primeng 数据表出现错误,因为它看不到作为数据传递的列表中的更改。

例如,我有一个数据表:

<p-dataTable selectionMode="single" [resizableColumns]="true" [rows]="20" [paginator]="true" [value]="queuedJobs" [rowHover]="true" [globalFilter]="gb" [style]="{'cursor':'pointer'}">

</p-dataTable>

当我修改“queuedJobs”数组时,数据表内容不会改变它在 Angular 2 中的样子。如何解决?你有同样的错误吗?

问候 马特乌斯

【问题讨论】:

    标签: angular primeng primeng-datatable


    【解决方案1】:

    我们的项目确实有同样的问题。 I think the answer lies in the way PrimeNG handles value changes:

    @Input() get value(): any[] {
        return this._value;
    }
    
    set value(val:any[]) {
        this._value = val ? [...val] : null;
        this.handleDataChange(); //filter the value 
    }
    

    我的猜测是,不知何故,&lt;p-dataTable/&gt; 的内部数组值与您正在修改的数组的实例不同,因此更改不会反映出来。

    一个临时的解决方法是在每次修改数组时强制数组成为一个新实例:

    //...after you've done your array updates
    this.queuedJobs = this.queuedJobs.slice(); // does a shallow clone of the array
    

    现在,调用&lt;p-dataTable/&gt;handleDataChange方法,重新渲染数据。

    这不是一个永久的解决方案。希望下一个版本的primeng能够解决这个问题。

    编辑:我现在意识到这是由于他们在内部设置数组的方式:

    this._value = val ? [...val] : null;
    

    这实际上是克隆了数组,因此您的更改将永远不会被反映。绝对是一个错误。

    编辑 2:正如 talpaz 指出的那样,this is a part of the design,因此您必须在添加或删除元素后创建一个新数组。

    【讨论】:

    • 创建新数组可以解决问题。恕我直言,如果这是有意设计的非直观功能。
    • @NullԀʇɹ92065 从 4.1.0 开始,您现在还可以在表格上指定 [immutable]="false" 以实现旧行为。
    • @"Michael Kucinski" 谢谢,我试试看。
    【解决方案2】:

    这似乎是“设计”的变化......

    https://github.com/primefaces/primeng/issues/2606

    【解决方案3】:

    其他人遇到同样的问题,请通过the part where they describe change detection

    DataTable 使用基于 setter 的检查或 ngDoCheck 来实现底层数据是否已更改以更新 UI。这是使用不可变属性配置的,当启用(默认)基于设置器的检测时,使用基于设置器的检测,因此您的数据更改(例如添加或删除记录)应始终创建新的数组引用而不是操作现有数组,因为 Angular 不会触发设置器,如果参考不变。例如,在删除项目时使用切片而不是拼接,或者在添加项目时使用扩展运算符而不是推送方法。另一方面,将不可变属性设置为 false 可以通过使用 ngDoCheck 和 IterableDiffers 来侦听更改而无需创建新的数据引用来消除此限制。基于 Setter 的方法更快,但是这两种方法都可以根据您的喜好使用。请注意,不可变属性还定义了 DataTable 如何处理数据,例如,当启用不可变时,排序不会改变原始数据,而是创建一个新的排序数据数组。

    在这之后还有一个分页器重置的例子

    export class DataTableDemo implements OnInit {
    
        cars: Car[];
    
        first: number = 0;
    
        constructor(private carService: CarService) { }
    
        ngOnInit() {
            this.carService.getCarsSmall().then(cars => this.cars = cars);
        }
    
        reset() {
            this.first = 0;
        }
    }
    <p-dataTable [value]="cars" [rows]="10" [paginator]="true" [(first)]="first">
        <p-column field="vin" header="Vin"></p-column>
        <p-column field="year" header="Year"></p-column>
        <p-column field="brand" header="Brand"></p-column>
        <p-column field="color" header="Color"></p-column>
    </p-dataTable>
    
    <button type="button" (click)="reset()" label="Reset"></button>

    这些选项应该可以很好地覆盖您!

    【讨论】:

      【解决方案4】:

      我在 html 的 p-datatable 标记中添加了 [immutable]="false"。它对我有用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-21
        • 2018-05-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多