Search code examples
angulardynamic-formsform-controlformgroups

Dynamic forms angular 4 giving error "Cannot find control with name:brave" for the first time


I have three tabs and by default first tab should open with details having form. I am generate each tab form dynamically with the example given in the angular io docs
https://angular.io/guide/dynamic-form

Below is the template

<div class="tab-content">          
    <form [formGroup]="myform" novalidate (submit)="onSubmit()">          
       <div   [ngClass]="{'dynamic-field-inline': feild.isTwoElementInTheRow}" class="form-group" *ngFor="let feild of templateData[dataIndex].details">
           <label [attr.for]="feild.name">{{feild.label}}</label>
               <div [ngSwitch]="feild.type">
                 <input *ngSwitchCase="'textbox'" class="form-control" [formControlName]="feild.key" [id]="feild.key" [type]="feild.type">
                    <select class="form-control" [id]="feild.key" *ngSwitchCase="'dropdown'" [formControlName]="feild.key">
                        <option *ngFor="let opt of feild.options" [value]="opt.key">{{opt.value}}</option>
                    </select>
                    <textarea *ngSwitchCase="'textarea'" class="form-control" [formControlName]="feild.key" rows="5" [id]="feild.key"></textarea>
                  </div>

                  <!--<div class="errorMessage" *ngIf="!myform.controls[feild.key].valid">{{feild.label}} is required</div>-->

                </div>
              <div class="form-row">
                  <button  type="submit" [disabled]="!myform.valid">Save</button>
              </div>
              </form>
            </div>

Below is the typescript code

let fields = [{
            "key": "brave",
            "type": "textbox",
            "label": "Bravery Rating",
            "required": true,
            "readable": true,
            "isTwoElementInTheRow": false
        },
        {
            "key": "brave1",
            "label": "Bravery Rating",
            "type": "dropdown",
            "isTwoElementInTheRow": false,
            "options": [{
                    "key": "solid",
                    "value": "Solid"
                },
                {
                    "key": "great",
                    "value": "Great"
                },
                {
                    "key": "good",
                    "value": "Good"
                },
                {
                    "key": "unproven",
                    "value": "Unproven"
                }
            ]
        },
        {
            "key": "brave2",
            "label": "Bravery Rating",
            "type": "textarea"
        },
        {
            "key": "brave3",
            "type": "textbox",
            "label": "Bravery Rating"

        }
    ];
let group: any = {};

fields.forEach(field => {
  group[field.key] = field.required ? new FormControl(field.value || '', Validators.required)
                                          : new FormControl(field.value || '');
});
this.myForm = new FormGroup(group);

Now when i am hitting url i am getting an error saying

 CreateTemplateComponent.html:31 ERROR Error: Cannot find control with name: 'brave'
at _throwError (forms.js:2432)
at setUpControl (forms.js:2300)
at FormGroupDirective.addControl (forms.js:6664)
at FormControlName._setUpControl (forms.js:7314)
at FormControlName.ngOnChanges (forms.js:7227)
at checkAndUpdateDirectiveInline (core.js:12358)
at checkAndUpdateNodeInline (core.js:13886)
at checkAndUpdateNode (core.js:13829)
at debugCheckAndUpdateNode (core.js:14722)
at debugCheckDirectivesFn (core.js:14663)

But when i switch tab it is working . Can anyone please help me.


Solution

  • Finally , I was getting this issue because my form was ready before my actual formGroups are ready.

    my html is

      <form [formGroup]="myform" novalidate (submit)="onSubmit()">
    
      <div class="form-group" *ngFor="let feild of templateData">
      //forms fileds
      </div>
    

    Now i have initialized

      myform: FormGroup = new FormGroup({});
    
      this.myform = data (Where all fields are converted into FormControl's)
    

    Then i have initiazed

      this.templateData = data['subnodes'];