AG Grid:通过 ComponentFactoryResolver 在组件中加载网格时未触发 gridReady 事件

Posted

技术标签:

【中文标题】AG Grid:通过 ComponentFactoryResolver 在组件中加载网格时未触发 gridReady 事件【英文标题】:AG Grid : gridReady event not triggered when loading grid in a component via ComponentFactoryResolver 【发布时间】:2021-02-22 13:11:42 【问题描述】:

在我的 Angular 10 应用程序中,我正在通过组件工厂解析器加载一个包含 AG Grid 的组件。

当我通过按钮触发工厂解析器时,一切正常。显示 Grid 并正确触发 gridReady 事件。

但是,如果我通过ngOnInit()ngAfterViewInit()等触发组件工厂解析器,则不会触发gridReady事件并且不会显示网格。

我尝试使用 ChangeDetectorRef 服务来强制进行更改检测,但这并没有改变任何东西。

这是组件工厂解析器的代码:

export class PlannerComponent implements OnInit 
  @ViewChild('ordersContainer', read: ViewContainerRef) container: ViewContainerRef;
  public orders = [];

  constructor(
    private componentFactoryResolver: ComponentFactoryResolver,
    private httpClient: HttpClient
  )  

  ngOnInit(): void 
    this.loadOpenOrders();
  

  loadOpenOrders() 
    this.httpClient.get('/orders')
      .pipe(map((result: any) => 
        const orders = result._embedded.orders;
        orders.forEach((function (order) 
          this.addOrder();
        ).bind(this))
      ))
      .subscribe()
  

  onGridReady(params) 
    this.gridApi       = params.api;
    this.gridColumnApi = params.columnApi;
    this.gridApi.sizeColumnsToFit();
  

  addOrder() 
    // Create component dynamically inside the ng-template
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(OrderComponent);
    const newOrder         = this.container.createComponent(componentFactory);

    // Push the component so that we can keep track of which components are created
    this.orders.push(newOrder);
  


在视图中,组件是这样加载的:

<div class="container">
  <div class="row">
    <div class="col-6">
      <div class="card card-custom gutter-b">
        <ag-grid-angular
          style="width: 100%; height: 600px;"
          class="ag-theme-alpine"
          [rowData]="ordersToPlan"
          [columnDefs]="columnDefs"
          [rowSelection]="rowSelectionType"
          (gridReady)="onGridReady($event)"   <==== Only triggered through button click, but not on ngOnInit()
          [animateRows]="true"
        >
        </ag-grid-angular>
      </div>
    </div>
    <div class="col-6">
      <button class="btn btn-success mb-5" (click)="addOrder()">Add a new Order</button>
      <div>
        <ng-template #ordersContainer>
        </ng-template>
      </div>
    </div>
  </div>
</div>

任何帮助表示赞赏:-)

【问题讨论】:

【参考方案1】:

我终于找到了问题所在。我需要强制执行更改检测,但在子组件中(我通过组件工厂解析器加载的那个)。

order.component.ts

constructor(
    private cd: ChangeDetectorRef
  )  

...

setTransport(transport: Transport): void 
    ...
    this.cd.detectChanges();
  

非常感谢所有尝试解决此问题的人!

【讨论】:

【参考方案2】:

我在您的代码中的一处看到了问题。

与其在pipe 运算符中调用addOrders,不如在get 调用的subscribe 部分中完成。

  loadOpenOrders() 
    this.httpClient.get('/orders')
      .subscribe((result: any) => 
        const orders = result._embedded.orders;
        orders.forEach(order => 
          this.addOrder();
        );
      );
  

为什么我认为这会有所帮助? - 也许变化检测周期可能与 rxjs Observablesubscribe 有关;并且由于您的代码在subscribe 之前/之外执行所有这些工作,因此可能会被周期遗漏。

由于我无法将这些代码作为评论,因此将其发布为答案。让我知道这个是否奏效。评论您收到的任何错误/您的观察结果。如果您能提供任何工作示例(plunk/stackblitz),将能够快速帮助您。

如果没有帮助,将删除此答案。

【讨论】:

【参考方案3】:

试试这个:

转换

public orders = [];

进入可观察对象:

private ordersBS = new BehaviourSubject<any[]>([]);
public orders$ = this.ordersBS.asObservable();

html

[rowData]="orders$ | async"

添加订单时:

this.ordersBS.next(newOrder);

这样,agGrid 将始终监听可观察的 orders$。

onGridReady 函数应该只被调用一次。

【讨论】:

以上是关于AG Grid:通过 ComponentFactoryResolver 在组件中加载网格时未触发 gridReady 事件的主要内容,如果未能解决你的问题,请参考以下文章

通过按钮选择 ag-grid-table 中的下一行(如果下一行在下一页上)?

Ag-grid isRowSelectable 条件不激活

Ag-grid 企业:通过用户交互取消选择范围选择中的单元格的可能性

ag-Grid:我如何对 ICellRendererAngularComp 进行单元测试

Ag-grid 过滤器菜单自动调整大小

将 ag-grid 列绑定到数组