1

I am working on an Angular 4.X project and I am trying to create some HTML input fields (mostly of type text) on button click. I am using Angular reactive forms and trying to achieve this using Angular FormArray. I have written the code on the plunker but it shows some error.

Following is the link for the plunk that I have created -- http://plnkr.co/edit/PCFD43GK91zo2ivQ9lf7?p=preview

For easy reference please find the code below --

//our root app component
import {Component, NgModule} from '@angular/core'
import {BrowserModule} from '@angular/platform-browser'
import { FormBuilder, FormGroup, Validators, FormArray, FormControl } from '@angular/forms';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

@Component({
  selector: 'my-app',
  template: `<hr>
              <div>  
                <form [formGroup]="orderForm" (ngSubmit)="OnSubmit(orderForm.value)">
                  <div>
                    <input type="text" formControlName="customerName"/>
                    <input type="text" formControlName="email"/>
                  </div>
                  <div formArrayName="items" *ngFor="let item of orderForm.get('items').controls; let i = index;">
                    <div [formGroupName]="i">
                      <input type="text" formControlName="name" placeholder="Item name"/>
                      <input type="text" formControlName="description" placeholder="Item description"/>
                      <input type="text" formControlName="price" placeholder="Item price"/>
                    </div>
                    Chosen name: {{ orderForm.controls.items.controls[i].controls.name.value }}
                  </div>
                  <button type="submit">Save</button>
                  <button type="button" (click)="addItem()">Add More</button>
                </form>
              <div>`,
})

export class App {

  constructor(private fb: FormBuilder) {  }

  public items:any[];
  public orderForm: FormGroup;



  ngOnInit() {
      this.orderForm = this.formBuilder.group({
        customerName: '',
        email: '',
        items: this.formBuilder.array([ this.createItem()])
      });
  }

 createItem(): FormGroup {
    return this.formBuilder.group({
      name: '',
      description: '',
      price: ''
    });
  }

  addItem(): void {
  this.items = this.orderForm.get('items') as FormArray;
  this.items.push(this.createItem());
  }

  public OnSubmit(formValue: any) {
        console.log(formValue);
    }

}

@NgModule({
  imports: [ BrowserModule, FormsModule, ReactiveFormsModule ],
  declarations: [ App ],
  bootstrap: [ App ]
})
export class AppModule {}

If anyone can figure out what is wrong with it, I will highly appreciate that.

1
  • Take a look at the answer I gave here, could be a solution. Commented Sep 22, 2017 at 12:36

2 Answers 2

1

you need a getter for your orderForm items and your variable name for FormBuilder should be either 'fb' what you declared in your contructor or 'formBuilder' what you are using everywhere

Fixed plunker

export class App {

  constructor(private formBuilder: FormBuilder) {  }

  public orderForm: FormGroup;



  ngOnInit() {
      this.orderForm = this.formBuilder.group({
        customerName: '',
        email: '',
        items: this.formBuilder.array([ this.createItem()])
      });
  }

 createItem(): FormGroup {
    return this.formBuilder.group({
      name: '',
      description: '',
      price: ''
    });
  }

   get items(): FormArray {
    return this.orderForm.get('items') as FormArray;
  };

  addItem(): void {
  this.items.push(this.createItem());
  }

  public OnSubmit(formValue: any) {
        console.log(formValue);
    }

}

html code

<div>  
                <form [formGroup]="orderForm" (ngSubmit)="OnSubmit(orderForm.value)">
                  <div>
                    <input type="text" formControlName="customerName"/>
                    <input type="text" formControlName="email"/>
                  </div>
                  <div formArrayName="items" *ngFor="let item of items.controls; let i = index;">
                    <div [formGroupName]="i">
                      <input type="text" formControlName="name" placeholder="Item name"/>
                      <input type="text" formControlName="description" placeholder="Item description"/>
                      <input type="text" formControlName="price" placeholder="Item price"/>
                    </div>
                    Chosen name: {{ orderForm.controls.items.controls[i].controls.name.value }}
                  </div>
                  <button type="submit">Save</button>
                  <button type="button" (click)="addItem()">Add More</button>
                </form>
              <div>
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks you so much. This helped.!!
Could you please tell me how do I use validation to the dynamically created fields ? I am doing the following but it throws error. createItem(): FormGroup { return this.formBuilder.group({ FirstName: ['',[Validators.required,Validators.pattern("[a-zA-Z]")]], MiddleName: ['',[Validators.pattern("[a-zA-Z]")]], LastName: ['',[Validators.pattern("[a-zA-Z]")]], }); }
0

You are importing private fb: FormBuilder but after this trying to call this.formBuilder.something. Change it to this.fb.something

If it still does not work, try putting your code from ngOnInit to the constructor method directly.

Comments

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.