AG Grid: событие gridReady не запускается при загрузке сетки в компонент через ComponentFactoryResolver

В моем приложении Angular 10 я загружаю через преобразователь фабрики компонентов компонент, содержащий AG 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>

Любая помощь приветствуется :-)


person Pascal Paulis    schedule 10.11.2020    source источник


Ответы (3)


Я наконец нашел проблему. Мне нужно было обеспечить обнаружение изменений, но в подкомпоненте (тот, который я загружаю через компонент Factory resolver).

In order.component.ts :

constructor(
    private cd: ChangeDetectorRef
  ) { }

...

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

Большое спасибо всем, кто пытался это решить!

person Pascal Paulis    schedule 24.11.2020

Я вижу проблему в одном месте вашего кода.

Вместо вызова addOrders внутри оператора pipe это должно было быть сделано в subscribe части вызова get.

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

Почему я думаю, что это может помочь? - возможно, цикл обнаружения изменений может иметь какое-то отношение к subscribe из rxjs Observable; и поскольку ваш код выполняет все эти вещи до / за пределами subscribe, цикл может быть пропущен.

Поскольку я не мог использовать этот код в качестве комментария, разместил это как ответ. Сообщите мне, если это сработает. Прокомментируйте любую полученную ошибку / наблюдаемое вами наблюдение. Если бы вы могли предоставить какой-либо рабочий пример (plunk / stackblitz), вы быстро помогли бы.

Удаляю этот ответ, если он бесполезен.

person Paritosh    schedule 20.11.2020

Попробуй это:

Перерабатывать

public orders = [];

в наблюдаемое:

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

HTML:

[rowData]="orders$ | async"

При добавлении заказа:

this.ordersBS.next(newOrder);

Таким образом, agGrid всегда будет слушать заказы $ observable.

Функция onGridReady должна вызываться только один раз.

person Marco Nascimento    schedule 23.11.2020