3
votes

AG Grid: événement gridReady non déclenché lors du chargement de la grille dans un composant via ComponentFactoryResolver

Sur mon application Angular 10, je charge via le résolveur de fabrique de composants un composant contenant une grille AG.

Lorsque je déclenche le résolveur d'usine via un bouton, tout fonctionne correctement. La grille s'affiche et l'événement gridReady est déclenché correctement.

Cependant, si je déclenche le résolveur de fabrique de composants via ngOnInit() ou ngAfterViewInit() etc., l'événement gridReady n'est pas déclenché et la grille ne s'affiche pas.

J'ai essayé d'utiliser le service ChangeDetectorRef pour forcer une détection de changement, mais cela n'a rien changé.

Voici le code du résolveur d'usine de composants:

<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>

Dans la vue, le composant est chargé comme ceci:

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);
  }
}

Toute aide est appréciée :-)


0 commentaires

3 Réponses :


2
votes

Je vois un problème à un endroit dans votre code.

Au lieu d'appeler addOrders dans l'opérateur de pipe , cela aurait dû être fait dans la partie subscribe de l'appel get .

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

Pourquoi je pense que cela pourrait aider? - peut-être que le cycle de détection des changements pourrait avoir quelque chose à voir avec l' subscribe de rxjs Observable ; et comme votre code fait toutes ces choses avant / en dehors de l' subscribe , il peut être manqué par le cycle.

Puisque je ne pouvais pas ces codes comme commentaire, poster ceci comme réponse. Laissez-moi savoir si cela fonctionne. Commentez toute erreur que vous obtenez / observation que vous avez. Si vous pouviez fournir un exemple de travail (plunk / stackblitz), vous serez en mesure de vous aider rapidement.

Supprimera cette réponse si ce n'est pas utile.


0 commentaires

2
votes

Essaye ça:

Convertir

this.ordersBS.next(newOrder);

en un observable:

[rowData]="orders$ | async"

HTML:

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

Lors de l'ajout d'une commande:

public orders = [];

De cette façon, agGrid sera toujours à l'écoute des commandes $ observables.

La fonction onGridReady est censée être appelée une seule fois.


0 commentaires

2
votes

J'ai finalement trouvé le problème. J'avais besoin d'appliquer la détection des changements, mais dans le sous-composant (celui que je charge via le résolveur d'usine du composant).

Dans order.component.ts :

constructor(
    private cd: ChangeDetectorRef
  ) { }

...

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

Un grand merci à tous ceux qui ont essayé de résoudre ce problème!


0 commentaires