Background
I receive client generated data from the server that contains HTML that I then use to create a dynamic component that gets injected and displayed in our client. The HTML I receive can contain one or many inputs that I need to bind to via Angular Reactive Forms.Attempt 1:
I attempted to tackle this requirement by simply using the[innerHTML]
property and creating dynamic Reactive Forms to bind to the inputs. However, that method fails due to technical limitations of using the innerHTML property. Once the HTML is rendered in the browser all properties are forced to lowercase text so any Angular directives or properties then fail. Such as *ngIf, *ngFor, [formGroup], formControlName
, etc... Angular uses camelCase for just about everything and therefor once it is forced to lowercase text it all is ignored and this method is no longer a viable solution.
Attempt 2:
This time around I attempted to utilize Angulars NgTemplateOutlet to dynamically add the HTML to the component and then create and bind to a Reactive Form. This at first seemed like a great solution, but ultimately in order to get the html to render it requires the use of the[innerHTML]
property, once again rendering this method useless (as described in my first attempt).
Attempt 3:
At last I discovered Dynamic Components and this solution is working partially. I can now succesfully create a well formed Angular HTML template that is rendered properly in the browser. However this only solves half of my requirement. At this point the HTML displays as expected, but I have been unable to create a Reactive Form and bind to the inputs.The Problem
I now have a Dynamic Component that generates HTML that contains inputs that I need to bind to by creating a Reactive Form.Attempt 4:
This attempt I placed all logic for creating the Reactive Form inside the Dynamic Component that gets created.By using this method the dynamic components HTML is displayed, but I get a new error: "ERROR Error: formGroup expects a FormGroup instance. Please pass one in."
The Solution
Working StackBlitz with solution
The solution is to create the Reactive Form in the parent component. Then use Angulars dependency injection and inject the parent component into the Dynamic Component.
By injecting the parent component into the dynamic component you will have access to all of the parents components public properties including the reactive form. This solution demonstrates being able to create and use a Reactive Form to bind to the input in a dynamically generated component.
Full code below
If I am reading this correctly, your Template (HTML) is outrunning your component initialization, specifically on the
FormGroup
. The best way to prevent this from happening is to attach an*ngIf
statement to your form on which you have bound yourFormGroup
. That way it won't render until yourFormGroup
has been defined.