Home > Enterprise >  Angular Dynamic Component Creation not rendering dynamic child components
Angular Dynamic Component Creation not rendering dynamic child components

Time:07-07

We've built a rather fancy dynamic component creation framework to build out complex forms based on json data. We have components that get created via

const questionComponent = FieldComponentMap[childField.shortName];    
viewContainerRef.createComponent<QuestionComponent>(questionComponent);

Those components may create child components of their own, etc, etc. It's all very elegant, and we like the design. We've got the whole thing "working", but it's not working well. Child, or perhaps grandchild components often don't render the first time around until something changes on the page. I'm sure we're just missing something simple, but we could use some more eyes to help us find what we're doing wrong.

We've tried moving all the dynamic component creation out of ngOnInit and into ngAfterContentInit, but that didn't help. We obviously want the complete form to render immediately.

Here's a StackBlitz demonstrating our issue (drastically simplified from our framework)... StackBlitz

CodePudding user response:

I think you're lost in the hierarchy.

To be more precisely, you're operating a wrong instance of FormGroup in

array-question-wrapper.component.ts

Try replacing

this.createChildQuestionComponents(this.formGroup);

with

this.createChildQuestionComponents(this.formGroup.get(
     [this.formArrayName, this.formArrayIndex]) as FormGroup);

Forked Stackblitz

Another option

When working with dynamically creating forms you don't need to wrap all your ng-templates with formGroup, formArrayName directives. They are not tied to your child dynamically created controls anyway.

So:

parent-array-question.component.ts

Replace

componentRef.instance.containingControl = this.formGroup;

with

componentRef.instance.containingControl = arrayItem;

array-question-wrapper.component.ts

template should be:

<div >
  <ng-template appQuestionHost></ng-template>
</div>

or just <ng-template appQuestionHost></ng-template> if you don't need any additional classes here or you can use host element to style it.

Forked Stackblitz 2

CodePudding user response:

I had issues with template portals that were instantiated within a component that was dynamically added. Setting a timeout to associate the template portal within the dynamically created component fixed it. I am not perfectly satisfied with that. But, it may give a hint as to why your controls are not being recognised.

  • Related