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 :-)
3 Réponses :
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.
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.
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!