2

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

8
  • 1
    Please provide the component source. You are mixing reactive and template driven form, it's not a good idea. Commented Dec 4, 2017 at 10:42
  • Component source is added in the question, Actually I am new in Angular. Commented Dec 4, 2017 at 10:52
  • Please help, how do I save user entered data in component's variable. @JEY Commented Dec 4, 2017 at 10:59
  • Try [(ngModel)] instead of ([ngModel]) Commented Dec 4, 2017 at 12:46
  • is it correct syntactically, I didn't seen this anywhere Commented Dec 4, 2017 at 12:53

1 Answer 1

2

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

Sign up to request clarification or add additional context in comments.

8 Comments

Thanks for your answer, but I'm getting an error by applying this solution, The error says: "Cannot find control with path". I think it is giving error because "value" is not the control name, I made a class of control with the required attributes. and while creating FormControl I pass my control class object as its first parameter.
I have added my Control class in question, Please help.
@WaleedShahzaib Well what I provided was just a sample, instead of value just apply your own form control names in the looping where you set the form groups to form array.
I tried it as well but it is not working either. I tried control.value.value(Control class attribute where I want to store entered data.) as formControlName,
a parent component can be when it has the child selector in parent like <child></child> also it can be a parent when you have <router-outlet></router-outlet> inside parent. When it comes to component communication (if that is behind this question) it means that when you have the child selector inside parent you can use @Input and @Output, whereas you cannot use that when child is behind a router-outlet. In that case you need to use service. Hopefully it helps :)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.