8

调整 ag-Grid 的大小(更改浏览器窗口的大小)并在两个选项卡之间切换时收到以下警告:

ag-Grid:尝试调用 sizeColumnsToFit() 但网格以零宽度返回,也许网格在屏幕上还不可见?

我在 Stackblitz 中重现了这种情况:

https://angular-jpmxjy.stackblitz.io/

这是测试应用程序的组成:

  • PrimeNG p-tabMenu 在组件:header.component
  • ag-Grid 在组件:delleverancer.component 和leverancer.component。

当您调整网格大小并在 tabMenu 'Leverancer' 和 'Delleverancer' 之间切换时,您将在 chrome 开发工具中看到警告错误。

你可以在这里看到代码:

https://stackblitz.com/edit/angular-jpmxjy

如何删除这个不需要的警告错误?

在此处输入图像描述

4

4 回答 4

8

这类错误通常意味着您的应用程序中存在内存泄漏。

查看您的代码后,我注意到您如何订阅window:resize事件

window.addEventListener("resize", function () { ...

您应该知道,即使在组件被销毁后,此订阅仍将存在。

你可以写removeEventListenerngOnDestroy钩子里。但是为此,您必须保留对原始附加功能的引用。更好的方法是使用专门的 Angular@HostListener装饰器来负责removeEventListener

@HostListener('window:resize')
onResize() {
  if (!this.gridApi) return;

  setTimeout(() => {
    this.gridApi.sizeColumnsToFit();
  });
}

分叉的 Stackblitz

为了不重复自己,您可以创建如下指令:

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>

Stackblitz 示例

于 2019-01-06T15:34:48.157 回答
5

旧线程,但对于反应答案和未来的受害者,我遇到了同样的问题,问题是用 componentWillUnmount 清理事件侦听器。

要查看您的事件侦听器发生了什么,请使用(在 Chrome 中)getEventListeners(window) 并观察您的组件如何添加它们,但在更改页面等时不要删除它们。在实施下面的解决方案后,您应该会看到事件侦听器被删除当您的组件被销毁时。

需要为侦听器使用函数,以便您有适当的参考来删除。

假设基于类的方法:

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>
 )
于 2019-08-02T17:58:09.407 回答
0

这对我有帮助

ngOnDestroy() {
    try { 
        if (this.gridApi) {
            this.gridApi.destroy();
            this.gridApi = false;
        }

    } catch (error) {

    }
}
于 2020-07-21T10:24:39.670 回答
0

在使用 Bootstrap Angular 选项卡时遇到了这个问题,但其他库的解决方案应该是类似的。希望这可以帮助其他仍在努力寻找解决方案的人。

  1. 每个 ag-grid 都需要有 onGridReady 函数。
  2. 显示网格的第一个选项卡在 DOM 中呈现时没有问题调整列的大小以适应它。
  3. 对于其他选项卡中的网格,请在选项卡更改时触发的事件中调用 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;
  }
}

于 2021-11-01T01:14:58.833 回答