Предупреждение 'нулевой ширины сетки' при использовании sizeColumnsToFit() ag-Grid на двух отдельных ag-гридах, отображаемых в меню вкладок
Получение предупреждения ниже при изменении размера ag-Grid (изменение размера окна браузера) и переключение между двумя вкладками:
ag-Grid: попытался вызвать sizeColumnsToFit(), но сетка возвращается с нулевой шириной, может быть, сетка еще не видна на экране?
Я воспроизвел ситуацию в Stackblitz:
https://angular-jpmxjy.stackblitz.io/
Вот состав тестового приложения:
- PrimeNG p-tabMenu в компоненте: header.component
- ag-Grid в компонентах: delleverancer.component и leverancer.component.
Вы увидите ошибку предупреждения в инструментах Chrome Dev, когда вы измените размер сетки и переключитесь между tabMenu 'Leverancer' и 'Delleverancer'.
Вы можете увидеть код здесь:
https://stackblitz.com/edit/angular-jpmxjy
Как мне удалить эту нежелательную ошибку предупреждения?
5 ответов
Подобные ошибки обычно означают, что в вашем приложении есть утечка памяти.
После просмотра вашего кода я заметил, как вы подписываетесь на window:resize
событие
window.addEventListener("resize", function () { ...
Вы должны знать, что эта подписка останется там даже после уничтожения компонента.
Вы могли бы написать removeEventListener
в ngOnDestroy
крюк. Но для этого вы должны сохранить ссылку на оригинальную прикрепленную функцию. Лучше было бы использовать выделенный Angular @HostListener
декоратор, который будет нести ответственность за removeEventListener
под крюком:
@HostListener('window:resize')
onResize() {
if (!this.gridApi) return;
setTimeout(() => {
this.gridApi.sizeColumnsToFit();
});
}
Чтобы не повторяться, вы можете создать директиву вроде:
AG-грид-resize.directive.ts
import { Directive, HostListener } from '@angular/core';
@Directive({
selector: '[ag-grid-resize]'
})
export class AgGridResizeDirective {
private gridApi;
@HostListener('window:resize')
onResize() {
if (!this.gridApi) return;
setTimeout(() => {
this.gridApi.sizeColumnsToFit();
});
}
@HostListener('gridReady', ['$event'])
onGridReady(params) {
this.gridApi = params.api;
params.api.sizeColumnsToFit();
}
}
Теперь все, что вам нужно, чтобы добавить это поведение, это добавить атрибут в вашу сетку:
<ag-grid-angular
...
ag-grid-resize <============
>
</ag-grid-angular>
Старый поток, но для ответа и будущих страдальцев у меня была такая же проблема, и проблема заключалась в очистке прослушивателя событий с помощью componentWillUnmount.
Чтобы увидеть, что происходит с вашими слушателями событий, используйте (в Chrome) getEventListeners (окно) и посмотрите, как ваши компоненты добавляют их, но не удаляют их при смене страниц и т. Д. После реализации решения ниже вы должны увидеть, что слушатели событий удалены. когда ваш компонент разрушен.
Необходимо использовать функцию для слушателя, чтобы у вас была надлежащая ссылка для удаления.
Предполагая подход на основе классов:
export class someAgGrid extends Component { your brilliance }
componentWillUnmount() {
window.removeEventListener('resize', this.daListener);
};
daListener = () => {
if (!this.gridApi) return;
setTimeout(() => { this.gridApi.sizeColumnsToFit(); }, 200);
};
firstDataRendered = (params) => {
this.gridApi = params.api;
this.gridApi.sizeColumnsToFit();
window.addEventListener('resize', this.daListener);
};
в функции рендеринга:
return (
<div className='ag-theme-material'>
<AgGridReact
...your stuff
onFirstDataRendered={this.firstDataRendered}
/>
</div>
)
Столкнулся с этой проблемой при использовании вкладок Bootstrap Angular, но решение для других библиотек должно быть аналогичным. Надеюсь, это поможет другим, кто все еще пытается найти решение.
- Каждая аг-сетка должна иметь функцию onGridReady.
- Сетка отображения первой вкладки не имеет проблем с размером столбцов, чтобы они соответствовали тому, как она отображается в DOM.
- Для сеток на других вкладках вызовите sizeColumnsToFit() в событии, срабатывающем при изменении вкладки (selectTab для Bootstrap). Проверьте документацию для других соответствующих библиотек.
HTML:
<tabset type="pills">
<tab heading="heading1" id="tab1">
<ag-grid-angular
class="ag-theme-balham ag-grid-table"
[rowData]="data1$ | async"
[defaultColDef]="defaultColDef"
[columnDefs]="columnDefs1"
(gridReady)="onGridReady1($event)"
>
</ag-grid-angular>
</tab>
<tab heading="heading2" id="tab2" (selectTab)="onSelect($event)">
<ag-grid-angular
class="ag-theme-balham ag-grid-table"
[rowData]="data2$ | async"
[defaultColDef]="defaultColDef"
[columnDefs]="columnDefs2"
(gridReady)="onGridReady2($event)"
>
</ag-grid-angular>
</tab>
<tabset>
Машинопись:
import { Component, OnInit} from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { ColDef, GridReadyEvent } from 'ag-grid-community';
import { TabDirective } from 'ngx-bootstrap/tabs';
@Component({
selector: 'app-tabs',
templateUrl: './tabs.component.html',
styleUrls: ['./tabs.component.css'],
})
export class TabsetComponent implements OnInit {
data1$ = new BehaviorSubject<any[]>([]);
data2$ = new BehaviorSubject<any[]>([]);
private gridApi2;
private gridColumnApi2;
defaultColDef: ColDef = {
sortable: true,
filter: true,
resizable: true,
};
columnDefs1: ColDef[] = [
{ headerName: 'Category', field: 'category' },
{ headerName: 'Name', field: 'name' },
];
columnDefs2: ColDef[] = [
{ headerName: 'Module', field: 'module' },
{ headerName: 'Approval', field: 'approvalName' },
];
constructor() {}
ngOnInit(): void {}
// Event fired on tab change, needed only for tabs that are not rendered on page laod
onSelect(event: TabDirective) {
switch (event.heading) {
case 'heading2':
return this.gridApi2.sizeColumnsToFit();
default:
return;
}
}
// tab displayed on page load can call sizeColumnsToFit() directly
onGridReady1(event: GridReadyEvent) {
event.api.sizeColumnsToFit();
}
onGridReady2(event: GridReadyEvent) {
this.gridApi2 = event.api;
this.gridColumnApi2 = event.columnApi;
}
}
Проблема для меня заключалась в том, что на странице были скрытые элементы div, которые также использовали ag-grids, и каждый раз при изменении размера окна те скрытые элементы div, содержимое которых еще не было сгенерировано, приводили к ошибке.
Изменение[hidden]
к*ngIf
избавился от ошибок для меня.
HTML
От
<div>
<app-summary>
[hidden]="showSummaryView"
></app-summary>
<app-detailed
[hidden]="showDetailedView"
></app-detailed>
</div>
к
<div>
<app-summary>
*ngIf="showSummaryView"
></app-summary>
<app-detailed
*ngIf="showDetailedView"
></app-detailed>
</div>
Это помогло мне
ngOnDestroy() {
try {
if (this.gridApi) {
this.gridApi.destroy();
this.gridApi = false;
}
} catch (error) {
}
}