On my Angular 10 app, I'm loading through the component factory resolver a component containing an AG Grid.
When I trigger the factory resolver through a button, everything works fine. The Grid is displayed and the gridReady
event is fired correctly.
However if I trigger the component factory resolver through through ngOnInit()
or ngAfterViewInit()
etc., the gridReady event is not triggered and the grid is not displayed.
I tried to use the ChangeDetectorRef service to force a change detection, but that didn't change anything.
This is the code for the component factory resolver:
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);
}
}
In the view, the component is loaded like this:
<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>
Any help is appreciated :-)
I finally found the problem. I needed to enforce change detection, but in the sub-component (the one I'm loading through the component Factory resolver).
In order.component.ts
:
constructor(
private cd: ChangeDetectorRef
) { }
...
setTransport(transport: Transport): void {
...
this.cd.detectChanges();
}
A big thanks to everyone who tried to solve this!
I see issue at one place in your code.
Instead of calling addOrders
within pipe
operator, it should have been done in the subscribe
part of the get
call.
loadOpenOrders() {
this.httpClient.get('/orders')
.subscribe((result: any) => {
const orders = result._embedded.orders;
orders.forEach(order => {
this.addOrder();
});
});
}
Why I think this could help? - maybe change detection cycle might have something to do with subscribe
of rxjs Observable
; and as your code is doing all those stuffs before/outside subscribe
, it might be getting missed by the cycle.
Since I could not these code as comment, posting this as answer. Let me know if this works. Comment any error you get / observation you have. If you could provide any working example (plunk/stackblitz), will be able to help you out quickly.
Will delete this answer if its not helpful.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With