Amit Anand
Amit Anand

Reputation: 1109

Create Input fields dynamically in Angular 2

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.

Upvotes: 1

Views: 7887

Answers (2)

JayDeeEss
JayDeeEss

Reputation: 1083

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>

Upvotes: 1

ForestG
ForestG

Reputation: 18085

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.

Upvotes: 0

Related Questions