0

Arrgh, Having problems with Dynamically built components using ReactiveForms.

Need to trigger and Mat-Dialog and load set of components in it - works fine. Need to build some of the components dynamically from a mapping array - works fine. Need to build nested reactive forms using CVA (control value assessor) - this is the problem.

I have a working nested form using CVA that updates the form data correctly ... Unless I build the components dynamically. If I use dynamic components they are ignored in the form updates. Not sure how to fix this. My app will be very complex network of forms, so need to figure this out!

I have used the Angular.io guide for dynamic components.

Angular.io - resolve dynamic components

and followed this guide for CVA implementation

In-Depth - using CVA's

Does anyone have any Ideas?? Had issues with Stackblitz so pushed code to gitHub

dev-dynamic-comp issue

cuznerdexter
  • 586
  • 5
  • 21

1 Answers1

0

Instead of using CVA use Sub -Form Component Approach to create app-content form in this way we can register our child form with parent FormGroup using ControlContainer.

Injecting ControlContainer in child component provide access to parent FormGroup then we can add desired form control using addControl method.

content.component.ts

import { Component, forwardRef, OnInit } from '@angular/core';
import { AbstractControl, ControlContainer, ControlValueAccessor, FormControl, FormGroup, NG_VALIDATORS, NG_VALUE_ACCESSOR, ValidationErrors, Validators } from '@angular/forms';

@Component({
  selector: 'app-content',
  templateUrl: './content.component.html',
  styleUrls: ['./content.component.scss']
})
export class ContentComponent implements OnInit {

  parent:FormGroup;
  constructor(private controlContainer:ControlContainer) { }

  ngOnInit(): void {
    this.parent = this.controlContainer.control as FormGroup;
     this.parent.addControl('contentInfoForm',new FormGroup({
      contentNotes: new FormControl("",[Validators.required]),
      contentData: new FormControl("", [Validators.required])
    }));
  }
}

component.html

<ng-container *ngIf="parent" [formGroup]="parent">
    <ng-container formGroupName="contentInfoForm">
        <div class="row">
            <label for="Content Notes"> Content Notes </label>
            <input type="text" formControlName="contentNotes" class="">
    </div>
            <div class="row">
                <label for="Content Data"> Content Data </label>
                <input type="text" formControlName="contentData" class="">
    </div>
    </ng-container>
</ng-container>

Forked Working Example

Chellappan வ
  • 23,645
  • 3
  • 29
  • 60
  • Thanks @chellappan. This looks good. I actually tried this method first, but must have messed it up somehow. Will try this solution and see if it works, then report the result. – cuznerdexter Nov 15 '20 at 14:38
  • Well, I finally got the controlGroup implementation working for my features. Still getting an expressionChanged error. I tried using AfterViewInit instead of OnInit but got even more errors. – cuznerdexter Nov 15 '20 at 16:08
  • So I have have tried your solution on my actual app and had the same success - the forms are communicating with the parent finally. Thanks, I tried so many different solutions, this is the only one that works for me. – cuznerdexter Nov 16 '20 at 10:18
  • Yes - still getting the expressionChanged error eg. ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: '{ "formTitle": "", "basicInfo": "", "addressInfo": "", "specialInfo": "" }'. Current value: '{ "formTitle": "", "basicInfo": "", "addressInfo": "", "specialInfo": "", "contentInfoForm": { "contentNotes": "", "contentData": "" } }'. at throwErrorIfNoChangesMode (core.js:8160) ... ... ... at DialogComponent_Template (dialog.component.html:16) – cuznerdexter Nov 16 '20 at 10:18
  • If you move form creation inside OnInit also it's throws error? – Chellappan வ Nov 16 '20 at 10:22