2
votes

I have an ng-container that describes all of my possible form field templates, essentially on a large switch statement depending on the field's metadata:

<ng-template #dynamicFormField let-field="inputField">
  <div *ngIf="field.dataTypeName == 'ShortText'">
    <mat-form-field class="col-md-6">
      <input matInput type="text" [placeholder]="field.attributeLabel" [formControlName]="field.attributeName">
    </mat-form-field>
  </div>

  <div *ngIf="field.dataTypeName == 'LongText'">
    <mat-form-field class="col-md-12">
      <input matInput type="text" [placeholder]="field.attributeLabel" [formControlName]="field.attributeName">
    </mat-form-field>
  </div>

  <div *ngIf="field.dataTypeName == 'Number'">
    <mat-form-field>
      <input matInput type="number" [placeholder]="field.attributeLabel" [formControlName]="field.attributeName">
    </mat-form-field>
  </div>
<ng-template>

I have a base formgroup, then one property of the form group is a form array, each element of which with its own formgroup. For example, the data model looks something like this:

{
  name: 'Article Name',
  description: 'Some description of the article',
  sections: [
    {
      sectionName: 'Rich text section',
      sectionContent: 'Some rich text'
    },
    {
      sectionName: 'Second section',
      sectionContent: 'Some rich text'
    }
  ]
}

where each of these fields has corresponding metadata describing its form properties.

I want to be able to reuse the input switch statement in both the base formgroup as well as the formgroups within the form array. However, the inside of the ng-container cannot access the formgroup specified by the formarray's formGroupName input:

<div *ngFor="let field of this.sectionTypeSchemas[section.value.sectionTypeId]">
  <div *ngIf="field.isVisible != false" formGroupName="{{i}}">
    <ng-container *ngTemplateOutlet="dynamicFormField;context:{ inputField:field }"></ng-container>
  </div>
</div>

The error I am running into is basically that the Angular cannot find the controls that are inside of the formarray's FormGroups (i.e. sectionName from data model), although there is no issue in finding the controls corresponding the base formgroup controls (name and description from the data model). Is there a way I can manually pass the formgroup reference to the ng-container? A short example can be seen here.

1
Why dont you use an extra component with @Input() Decorator for this?MullisS
@MullisS I tried but there's still no way to explicitly pass a formgroup reference to it. You run into the same context errors.Joe H
Could you make a minimum example on stackblitz?MullisS
@MullisS Sure check it out here: link. As you can see, the fields render, but can't find the formcontrols associated with them.Joe H
Even the answer of Erbenskönig is correct, you should bether write a component for that, since you want your component not to know the form structure of the form. Take a look of this: stackblitz.com/edit/…MullisS

1 Answers

3
votes

First of all I would probably go with a subcomponent rather than the ng-template as it was suggested in the comments above, too.

Nevertheless, there are two things that needs to be fixed in order to get your example working

Using FormControls inside another component or ng-template

Everytime you use a formControl of a formGroup inside a ng-template, you need to make sure you add a tag having the formGroup binding as well inside your ng-template, if the form-tag is placed outside the ng-template.

In your case there is something special, because the formGroup inside your ng-template is actually a subFormGroup - the formGroup for each formArrayItem

FormArray binding

If you are binding to a formArray you need to keep in mind, that you need the formArrayName on the outside control as well as the binding to the index. Please have a look here for further explanation: FormArray binding

One more thing

You have a typo inside you stackblitz: secitonHeader rather than sectionHeader.


Here is a working : stackblitz