1

I'm following this example: http://plnkr.co/edit/hQ6RtzCfPosfQl4HlbZQ?p=preview to dynamically add and remove form elements.

html: in this file eventForm.controls.filters gives a Identifier 'filters' is not defined. __type does not contain such a member. property controls of FormGroup message, even though the code works, and the selects are not independent. Selecting one level populates all level selects.

<table class="example-full-width" cellspacing="0" formArrayname="filters" *ngFor="let filters of eventForm.controls.filters.controls; let i=index">
  <span>Address {{i + 1}}</span>
   <span *ngIf="eventForm.controls.filters.controls.length > 1" (click)="removeFilters(i)">x</span>
  <tr>
    <td>
      <md-select [(ngModel)]="filterUserOcc" [ngModelOptions]="{standalone: true}" placeholder="Occupation" (ngModelChange)="filterUserOccupation()">
        <md-option [value]="null">Occupation</md-option>
        <md-option *ngFor="let occupation of occupations | async" [value]="occupation.occupation">
          {{ occupation.occupation }}
        </md-option>
      </md-select>
    </td>
  </tr>
  <tr>
    <td>
      <md-select [(ngModel)]="filterUserLvl" [ngModelOptions]="{standalone: true}" placeholder="Level" (ngModelChange)="filterUserLevel()">
        <md-option [value]="null">Level</md-option>
        <md-option *ngFor="let level of levels | async" [value]="level.level">
          {{ level.level }}
        </md-option>
      </md-select>
    </td>
  </tr>
</table>

app.module.ts

...
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
...


imports: [
...
    ReactiveFormsModule,
 ...
  ],

component.ts

...
import { FormGroup, FormControl, FormArray, FormBuilder, Validators } from '@angular/forms';
...

export class NewEventComponent implements OnInit {

  eventForm: FormGroup;
...


  constructor(
...
    private formBuilder: FormBuilder,
...
  ) {
...
  }

ngOnInit() {
    this.eventForm = this.formBuilder.group({
...
      filters: this.formBuilder.array([
        this.initFilters()
      ])
    });

  }

initFilters() {
    return this.formBuilder.group({
      level: ['', Validators.required],
      occupation: ['']
    });
  }

  addFilters() {
    const control = <FormArray>this.eventForm.controls['filters'];
    control.push(this.initFilters());
  }

  removeFilters(i: number) {
    const control = <FormArray>this.eventForm.controls['filters'];
    control.removeAt(i);
  }

1 Answer 1

1

This is because you are using two-way-binding with just one variable for example for level, i.e [(ngModel)]="filterUserLvl", so when you make a change, it means that all your level's have the same value in the form.

Two-way-binding is highly discouraged when using reactive forms, the form controls are there to be used instead of ngModel.

Also noticed you were missing formGroupName for each form group inside your array, so I modified it to..

<div formArrayName="filters">
  <table *ngFor="let filters of eventForm.controls.filters.controls; let i=index" 
       [formGroupName]="i">
....

and then just remove the ngModel and ngModelChange from your your template and it works fine!

Seems you want a change event fired when changing the select, for that you can pass the actual form control.

DEMO

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

6 Comments

"Two-way-binding is highly discouraged when using reactive forms, the form controls are there to be used instead of ngModel." Indeed, I agree with you, however until today I couldn't find it in docs or anywhere. Did you?
@developer033 I was actually thinking of editing out that from my answer before, but I forgot :P Just have noticed that using two-way-binding usually ends in catastrophic results, as probably you have :D But you are correct, I shouldn't claim something I have no proof of :P It is completely true that I have also not found anything that says that they shouldn't be used together. The closest thing I have found is just what is explained as why ngModel isn't included in reactiveformsmodule.
@developer033 quote from: angular.io/guide/reactive-forms : You don't create Angular form control objects. Angular directives create them for you, using the information in your data bindings. You don't push and pull data values. Angular handles that for you with ngModel. Angular updates the mutable data model with user changes as they happen. For this reason, the ngModel directive is not part of the ReactiveFormsModule.*
Everything works! But eventForm.controls.filters is giving me a warning. [Angular] Identifier 'filters' is not defined. '__type' does not contain such a member. Any idea why? It's also crashing the build process.
The warning is in my code editor. I m using Visual Studio Code. The code works on localhost. But it won't build because of it. I ll send the error that's thrown when building later. I did a control.log of eventForm and controls.filters exists.
|

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.