PrimeNG p-table 延迟加载和多重排序 - 进入循环 - 超出最大调用堆栈大小

PrimeNG p-table Lazy loading and Multi Sort - Goes in Loop - Maximum call stack size exceeded

Stackblitz:https://stackblitz.com/edit/primeng-p-table-multisort

配置:
"@angular/cli": "~7.0.2", "primeng": "7.0.5",

我有一个通过延迟加载实现的 PrimeNG p-table。需要添加多列排序。

Stackblitz 上面的示例代码link。

<p-table [columns]="cols" [value]="cars1" [lazy]="true" [lazyLoadOnInit]="false" (onLazyLoad)="loadList($event)" sortMode="multiple" [multiSortMeta]="multiSortMeta">

如果它是单一排序模式,这可以正常工作。

出现错误 ERROR RangeError: Maximum call stack size exceeded

它应该是一个简单的实现,但无法理解这里缺少什么或者 PrimeNG 不支持它。

感谢任何帮助。

这个问题是因为this.cdRef.detectChanges();原因如下 loadList 绑定到 HTML.

中的 (onLazyLoad)="loadList($event)"

每次发生分页、排序和过滤时,PrimeNg 都会调用该事件。因此,当我们加载和添加排序事件时,它会一直调用。 Angular 每次都会调用更改检测,这会导致错误 ERROR RangeError: Maximum call stack size exceeded

loadList($event: any = {}) {
this.cars1 = [
  {
    vin: "a1653d4d",
    brand: "VW",
    year: 1998,
    color: "White",
    price: 10000
  },
  {
    vin: "ddeb9b10",
    brand: "Mercedes",
    year: 1985,
    color: "Green",
    price: 25000
  }
];
this.cdRef.detectChanges(); // this is the issue

}

已修改

ngOnInit() {
  this.cols = [
  { field: "vin", header: "Vin" },
  { field: "year", header: "Year" },
  { field: "brand", header: "Brand" },
  { field: "color", header: "Color" }
  ];

this.multiSortMeta = [
  { field: "year", order: 1 },
  { field: "brand", order: -1 }
];
 this.loadList();
}

loadList($event: any = {}) {
this.cars1 = [
  {
    vin: "a1653d4d",
    brand: "VW",
    year: 1998,
    color: "White",
    price: 10000
  },
  {
    vin: "ddeb9b10",
    brand: "Mercedes",
    year: 1985,
    color: "Green",
    price: 25000
  }
];
// this.cdRef.detectChanges();
}

底线是 this.cdRef.detectChanges(); 如果您正在使用它,请在应用程序的任何地方小心谨慎地使用它。

updated stackblitz

已更新 Stackblitz:https://stackblitz.com/edit/primeng-p-table-multisort

它通过原型链覆盖 PrimeNG Table - sortMultiple 方法。

旧代码:

Table.prototype.sortMultiple = function () {
    var _this = this;
    if (this.multiSortMeta) {
        if (this.lazy) {
            this.onLazyLoad.emit(this.createLazyLoadMetadata());
        }
        else if (this.value) {
            if (this.customSort) {
                this.sortFunction.emit({
                    data: this.value,
                    mode: this.sortMode,
                    multiSortMeta: this.multiSortMeta
                });
            }
            else {
                this.value.sort(function (data1, data2) {
                    return _this.multisortField(data1, data2, _this.multiSortMeta, 0);
                });
            }
            if (this.hasFilter()) {
                this._filter();
            }
        }
        this.onSort.emit({
            multisortmeta: this.multiSortMeta
        });
        this.tableService.onSort(this.multiSortMeta);
    }
};  

新代码:

Table.prototype.sortMultiple = function () {
    const _this = this;
    if (this.multiSortMeta) {
        if (this.lazy) {
            // additional conditions added
            if (this.lazyLoadOnInit || (!this.lazyLoadOnInit && this.initialized)) {
                this.onLazyLoad.emit(this.createLazyLoadMetadata());
            }
        } else if (this.value) {
            if (this.customSort) {
                this.sortFunction.emit({
                    data: this.value,
                    mode: this.sortMode,
                    multiSortMeta: this.multiSortMeta
                });
            } else {
                this.value.sort(function (data1, data2) {
                    return _this.multisortField(data1, data2, _this.multiSortMeta, 0);
                });
            }
            if (this.hasFilter()) {
                this._filter();
            }
        }
        this.onSort.emit({
            multisortmeta: this.multiSortMeta
        });
        this.tableService.onSort(this.multiSortMeta);
    }
};