2
votes

Hello I am using Angular reactive forms, I have used FormArray to add form controls dynamically. I am using ngModel directive to store user entered data in components variable. but it not storing it in components variable. my code is:

<form [formGroup]="reviewForm" (ngSubmit)="onSubmit()">
  <div class="example-label">
    <span class='block'>    
          <span *ngIf="selectedForm">
                  <h2 class="example-heading">{{displayForm}} </h2>
          </span>
    <div formArrayName="controlArray">
      <div *ngFor="let control of reviewForm.get('controlArray').controls; let i = index">
        <table>
          <tr>
            <td> <span *ngIf="control.value.controlType == 'text'">
          <md-form-field class="example-full-width">
            <input mdInput type="text" placeholder="{{control.value.placeholder}}" 
            ([ngModel])="control.value.value" > <!--user entered data is not storing in control.value.value -->
          </md-form-field>  
      </span></td>

          </tr>
        </table>
      </div>
      <button md-raised-button color="primary" type="submit" [disabled]="!reviewForm.valid">Submit</button>
    </div>
    </span>
  </div>
</form>

Here is the component class code:

export class FormListComponent {

  formsDb: FormData[];
  selectedForm: FormData;
  displayForm: String;
  test: String;
  reviewForm = new FormGroup({
    'controlArray': new FormArray([])
  });
  constructor(public formService: FormService, public authGuardService: AuthGuardService) {
    console.log('form-list is logged in 0528', this.authGuardService.authService.isLoggedIn);
  }

  ngOnInit() {
    this.reviewForm = new FormGroup({
      'controlArray': new FormArray([
      ])
    });
    this.showDefaultForm();
  }



  addForm() {
    this.displayForm = this.selectedForm.formName;
    this.reviewForm.setControl('controlArray', new FormArray([]));  //to reset FormArray               
    console.log('selected form 0528', this.selectedForm);
    for (let control of this.selectedForm.controlsArr) {
      const myControl: Control = new Control(control.controlType, control.label, control.required,
        control.placeholder, control.options);

      var controlArg: FormControl;
      if (control.required)
        controlArg = new FormControl(myControl, Validators.required);
      else
        controlArg = new FormControl(myControl);

      (<FormArray>this.reviewForm.get('controlArray')).push(controlArg);
    }
  }

  onSubmit() {
    console.log('submitted form 0528', this.reviewForm);
  }
}

Here is my Control class, I pass its object to FormControl constructor:

export class Control{  
    constructor(public controlType?:string, public label?:string, public required?:boolean ,public placeholder?:string, 
      public options?:string[], public value?:string){  }
  }

to check whether user entered data is stored in component's variable I logged my FormGroup variable i.e. reviewForm in this case. No data is saved in it. Please help, Thanks

1
Please provide the component source. You are mixing reactive and template driven form, it's not a good idea.JEY
Component source is added in the question, Actually I am new in Angular.Waleed Shahzaib
Please help, how do I save user entered data in component's variable. @JEYWaleed Shahzaib
Try [(ngModel)] instead of ([ngModel])Terje
is it correct syntactically, I didn't seen this anywhereWaleed Shahzaib

1 Answers

2
votes

I would suggest not using ngModel in reactive forms. Utilize the form controls instead for your reactive form, so remove value and [(ngModel)]. Here's a simplified version of your code for you to get the idea. Build the form, and if you are getting some default values, iterate that array and push formgroups to your formArray:

constructor(private fb: FormBuilder) {
  this.reviewForm = fb.group({
    controlArray: fb.array([])
  })
  let controlArr = this.reviewForm.controls.controlArray as FormArray
  // arr contains your default values
  this.arr.forEach(x => {
    controlArr.push(fb.group({
      controlType: [x.controlType],
      value: [x.value]
    }))
  })
}

Then in your template, switch to using formControlName for your controls, and also add formGroupName for each formgroup in your FormArray:

<div formArrayName="controlArray">
  <!-- add formGroupName -->
  <div *ngFor="let control of reviewForm.get('controlArray').controls; 
               let i = index" 
               [formGroupName]="i">
    <table>
      <tr>
        <td> 
          <span *ngIf="control.value.controlType == 'text'">
            <div class="example-full-width">
              <input type="text" formControlName="value">
             </div>  
          </span>
        </td>
      </tr>
    </table>
  </div>
</div>

StackBlitz