James
James

Reputation: 1219

Dynamically add new fields on a click event?

Here is my FormGroup:

this.productGroup = this.fb.group({
  name: ['', Validators.compose([Validators.required, Validators.maxLength(80)])],
  desc: ['', Validators.maxLength(3000)],
  category: ['', Validators.required]
  variants: this.fb.array([
    this.fb.group({
      type: '',
      options: ''
    })
  ])
});

I need to dinamically add type and options control fields after the user click on a button. FormArray should look like this after User Input: [ {type: 'size', options: 'Small', 'Big'}, {type: 'color', options: 'red', 'blue, 'yellow'}, ... ].

Here whats I'm trying to do:

// Add new item to FormArray
addItem(): void {
  this.variantsArray = this.productGroup.get('variants') as FormArray;
  this.variantsArray.push(this.fb.group({
    type: '',
    options: ''
  }));
}

// Template
<form [formGroup]="productGroup">
  // inputs...
  <div formArrayName="variants" *ngFor="let item of productGroup.controls['variants']; let i = index;">
      <div [formGroupName]="i">
        <div class="row">
          <mat-form-field class="col-12">
            <input formControlName="type">
          </mat-form-field>
        </div>
        <div class="row">
          <mat-form-field class="col-12">
            <input formControlName="options">
          </mat-form-field>
        </div>
      </div>
      <div class="row">
        <a href="javascript:" (click)="addItem()"> Adicionar Variante </a>
        <a href="javascript:" (click)="removeItem(i)" *ngIf="i > 0"> Remover Variante </a>
      </div>
    </div>
</form>

How to make it work?

Upvotes: 1

Views: 630

Answers (2)

Sebastian M&#252;nster
Sebastian M&#252;nster

Reputation: 575

I don't know exactly what you want to achieve but I think I got your problem.

The following code:

variants: this.fb.array([
    this.fb.group({
      type: '',
      options: ''
    })
  ])

does not produce an array, so you can't iterate over it with *ngFor.

If you look a little deeper into it you will see that

productGroup.controls['variants']

has a property with the controls.

So just change the *ngFor to:

*ngFor="let item of productGroup.controls['variants'].controls; let i = index;"

and you should be fine.

Upvotes: 1

nircraft
nircraft

Reputation: 8468

For adding the formElemnt dynamically in the reactive form, you need to first create the form element or a form group and push it in the original formarry for that field.

EX: i have a customerForm like below

this.customerForm = this.fb.group({
  firstName: ['', [Validators.required, Validators.minLength(3)]],
  lastName: ['', [Validators.required, Validators.maxLength(50)]],
  emailGroup: this.fb.group({
    email: ['', [Validators.required, Validators.email]],
    confirmEmail: ['', Validators.required],
  }, { validator: emailMatcher }),
  phone: ''
  addresses: this.fb.array([this.createAddress()])
});

On click of add Address in View I can call a function in component that will push a new address to the addresses array in form.

  addAddress(): void {
   this.addresses.push(this.createAddress());
  }

 createAddress(): FormGroup {
   return this.fb.group({
      street1: ['', Validators.required],
      street2: '',
      city: '',
      state: '',
      zip: ''
   });
 }

In your view you can iterate over this address array and display the addresses. Initially it won't show as the array value will be empty! Hope it Helps.

Upvotes: 0

Related Questions