p-table PrimeNG Ленивая загрузка и множественная сортировка - Зацикливается - Превышен максимальный размер стека вызовов


person Kunal Dethe    schedule 27.12.2019    source источник
comment
Может кто-нибудь сказать мне, почему голосование close?   -  person Kunal Dethe    schedule 30.12.2019
comment
ваша демонстрация не показывает никаких проблем?   -  person malbarmavi    schedule 30.12.2019
comment
Серьезно, понятия не имею, как ошибка остановилась. Конечно, сегодня я обновил демонстрационный код, чтобы подробно объяснить @AbhinavKumar проблему, но ошибка по-прежнему показывалась. Моя единственная проблема сейчас в том, что loadList() вызывается через p-table, хотя значение lazyLoadOnInit установлено на false. Я не хочу, чтобы стол делал это. На pagination и sort должно, а на init нет.   -  person Kunal Dethe    schedule 30.12.2019


Ответы (2)


Эта проблема возникла из-за this.cdRef.detectChanges(); Вот почему loadList привязан к (onLazyLoad)="loadList($event)" в HTML.

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(); нужно использовать осторожно и разумно в любом месте приложения, если вы его используете.

обновлен stackblitz

person Abhinav Kumar    schedule 30.12.2019
comment
loadList был вызван с использованием тайм-аута для имитации вызова API в моей ссылке stackblitz. Он работает, если loadList() вызывается напрямую, но с тайм-аутом он зацикливается. Пожалуйста, попробуйте и проверьте. - person Kunal Dethe; 30.12.2019
comment
обновил тот же stackblitz. Вы можете вызвать обнаружение изменений, когда уверены в этом. Ну, это была проблема здесь, даже если есть вызов API, вы можете вызвать форму там, просто не добавляйте обнаружение изменений в этот метод. Это должно работать без этого, в примере с PrimeNG они никогда не используют это. - person Abhinav Kumar; 30.12.2019
comment
Проверьте мой обновленный stackblitz. Вызов метода с settimeout и возврат данных с settimeout — это разные сценарии. Кроме того, если sortMode изменяется с multiple на single, loadList никогда не вызывается таблицей из-за того, что флаг lazyLoadOnInit установлен на false. Но если sortMode установлено в multiple, вызывается loadList, чего не должно быть. Проверьте консоль. - person Kunal Dethe; 30.12.2019

Обновленный 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);
    }
};
person Kunal Dethe    schedule 30.12.2019