在两个单独的 ag-Grid 上使用 ag-Grid 的 sizeColumnsToFit() 时出现警告 'grid zero width',由选项卡菜单显示
Warning 'grid zero width' when using ag-Grid's sizeColumnsToFit() on two separate ag-Grids, displayed by a tab menu
调整 ag-Grid 大小时(更改浏览器大小 window)并在两个选项卡之间切换时收到以下警告:
ag-Grid: tried to call sizeColumnsToFit() but the grid is coming back
with zero width, maybe the grid is not visible yet on the screen?
我在 Stackblitz 中重现了这种情况:
https://angular-jpmxjy.stackblitz.io/
下面是测试应用的组成:
- 组件中的 PrimeNG p-tabMenu:header.component
- ag-Grid 在
组件:delleverancer.component 和 leverancer.component.
您将在 chrome 开发工具中看到警告错误,
当您调整网格大小并在 tabMenu 'Leverancer' 和 'Delleverancer'.
之间切换时
你可以在这里看到代码:
https://stackblitz.com/edit/angular-jpmxjy
如何删除这个不需要的警告错误?
这类错误通常意味着您的应用程序存在内存泄漏。
查看您的代码后,我注意到您如何订阅 window:resize
事件
window.addEventListener("resize", function () { ...
你应该知道,即使在组件被销毁后,这个订阅仍然存在。
你可以在ngOnDestroy
钩子里写[=15=]。但为此你必须保持对原始附加功能的引用。更好的方法是使用专用 Angular @HostListener
装饰器,它将负责 removeEventListener
挂钩:
@HostListener('window:resize')
onResize() {
if (!this.gridApi) return;
setTimeout(() => {
this.gridApi.sizeColumnsToFit();
});
}
为了不重复自己,您可以创建如下指令:
ag-grid-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 清理事件监听器。
要查看您的事件侦听器发生了什么,请使用 (in Chrome) getEventListeners(window) 并观察您的组件如何添加它们,但在您更改页面等时不要删除它们。实施下面的解决方案后,您应该会看到当您的组件被销毁时事件侦听器被删除。
需要为侦听器使用一个函数,以便您有适当的引用来删除。
假设基于 class 的方法:
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>
)
这对我有帮助
ngOnDestroy() {
try {
if (this.gridApi) {
this.gridApi.destroy();
this.gridApi = false;
}
} catch (error) {
}
}
在使用 Bootstrap Angular 选项卡时遇到此问题,但其他库的解决方案应该类似。希望这可以帮助其他仍在努力寻找解决方案的人。
- 每个ag-grid都需要有onGridReady函数。
- 显示网格的第一个选项卡在调整列大小方面没有问题,因为它在 DOM 中呈现。
- 对于其他选项卡中的网格,在选项卡更改时触发的事件中调用 sizeColumnsToFit()(Bootstrap 的 selectTab)。检查其他相应库的文档。
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;
}
}
调整 ag-Grid 大小时(更改浏览器大小 window)并在两个选项卡之间切换时收到以下警告:
ag-Grid: tried to call sizeColumnsToFit() but the grid is coming back with zero width, maybe the grid is not visible yet on the screen?
我在 Stackblitz 中重现了这种情况:
https://angular-jpmxjy.stackblitz.io/
下面是测试应用的组成:
- 组件中的 PrimeNG p-tabMenu:header.component
- ag-Grid 在 组件:delleverancer.component 和 leverancer.component.
您将在 chrome 开发工具中看到警告错误, 当您调整网格大小并在 tabMenu 'Leverancer' 和 'Delleverancer'.
之间切换时你可以在这里看到代码:
https://stackblitz.com/edit/angular-jpmxjy
如何删除这个不需要的警告错误?
这类错误通常意味着您的应用程序存在内存泄漏。
查看您的代码后,我注意到您如何订阅 window:resize
事件
window.addEventListener("resize", function () { ...
你应该知道,即使在组件被销毁后,这个订阅仍然存在。
你可以在ngOnDestroy
钩子里写[=15=]。但为此你必须保持对原始附加功能的引用。更好的方法是使用专用 Angular @HostListener
装饰器,它将负责 removeEventListener
挂钩:
@HostListener('window:resize')
onResize() {
if (!this.gridApi) return;
setTimeout(() => {
this.gridApi.sizeColumnsToFit();
});
}
为了不重复自己,您可以创建如下指令:
ag-grid-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 清理事件监听器。
要查看您的事件侦听器发生了什么,请使用 (in Chrome) getEventListeners(window) 并观察您的组件如何添加它们,但在您更改页面等时不要删除它们。实施下面的解决方案后,您应该会看到当您的组件被销毁时事件侦听器被删除。
需要为侦听器使用一个函数,以便您有适当的引用来删除。
假设基于 class 的方法:
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>
)
这对我有帮助
ngOnDestroy() {
try {
if (this.gridApi) {
this.gridApi.destroy();
this.gridApi = false;
}
} catch (error) {
}
}
在使用 Bootstrap Angular 选项卡时遇到此问题,但其他库的解决方案应该类似。希望这可以帮助其他仍在努力寻找解决方案的人。
- 每个ag-grid都需要有onGridReady函数。
- 显示网格的第一个选项卡在调整列大小方面没有问题,因为它在 DOM 中呈现。
- 对于其他选项卡中的网格,在选项卡更改时触发的事件中调用 sizeColumnsToFit()(Bootstrap 的 selectTab)。检查其他相应库的文档。
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;
}
}