1

I have to dynamically create a form with data received from the server with the option of adding and removing input fields for each existing input fields.

This is the data i receive from the server

documents = [{id: 1, service_item_id: 311101, name: 'document 1'}, {id: 2, service_item_id: 311102,, name: 'document 2'}, {id: 3, service_item_id: 311103,, name: 'document 3'}, {id: 4, service_item_id: 311104,, name: 'document 4'}]

I have created a function to create the form

createControls(controls) {
    console.log(controls);
    for (let control of controls) {
        const newFormControl = new FormControl();
        this.myForm.addControl(control.service_item_id, newFormControl);
    }
}

this.createControls(this.documents);

And in the Html I have created this

<form [formGroup]="myForm" (ngSubmit)="submitForm()">
    <div *ngFor="let c of documentation; let index = index">
        <label>
            {{ c.name}}
        </label>
        <input type="number" [formControlName]="c.service_item_id" [placeholder]="c.name" />
        <button class="btn btn-primary btn-sm" (click)="add(c.service_item_id)">Add</button>
        <button class="btn btn-primary btn-sm" (click)="remove(c.service_item_id, index)">Remove</button>
    </div>
    <button type="submit" class="btn btn-primary btn-small">Submit</button>
</form>

My add and remove functions are

add(item): void {
    (this.myForm.get(item) as FormArray).push(
      this.fb.control(null)
    );
  }

  remove(item, index) {
    (this.myForm.get(item) as FormArray).removeAt(index);
  }

Only the form is getting created but add and remove buttons are not working.

Please do help me resolve this issue. Thanks in advance

2 Answers 2

3

I think what will work best for your situation is to use FormArray. With FormArray you can push and remove items just like you would do with a normal array

  myForm = this.fb.group({
    documents: this.fb.array([])
  });

  get documentsControl(): FormArray {
    return this.myForm.get("documents") as FormArray;
  }
  documents = [
    { id: 1, service_item_id: 311101, name: "document 1" },
    { id: 2, service_item_id: 311102, name: "document 2" },
    { id: 3, service_item_id: 311103, name: "document 3" },
    { id: 4, service_item_id: 311104, name: "document 4" }
  ];
  ngOnInit() {
    this.documents.forEach(document =>
      this.documentsControl.push(
        this.fb.group({
          id: [document.id],
          name: [document.name],
          service_item_id: [document.service_item_id]
        })
      )
    );
  }
  constructor(private fb: FormBuilder) {}
  submitForm() {}
  add() {
    this.documentsControl.push(
      this.fb.group({
        id: [null],
        name: [null],
        service_item_id: [null]
      })
    );
  }
  remove(index) {
    this.documentsControl.removeAt(index);
  }

to add items we use push while to remove items we use removeAt

Below is the html

<form [formGroup]="myForm" (ngSubmit)="submitForm()">
    <ng-container formArrayName='documents'>
      <div *ngFor="let c of documentsControl.controls; let index = index" [formGroupName]='index'>
        <label>
            {{ c.value.name}}
        </label>
        <input type="number" formControlName="service_item_id" placeholder="name" />
        <button class="btn btn-primary btn-sm" (click)="add()">Add</button>
        <button class="btn btn-primary btn-sm" (click)="remove(index)">Remove</button>
    </div>
    </ng-container>
    <button type="submit" class="btn btn-primary btn-small">Submit</button>
</form>

Edit

To add items below there clicked button we can implement insert()

  insert(index) {
    const serviceItenId = this.documentsControl.controls[index].get('service_item_id').value
    this.documentsControl.insert(
      index + 1,
      this.fb.group({
        id: [null],
        name: [null],
        service_item_id: [serviceItenId]
      })
    );
  }

I have updated the below Demo to reflect this

See Demo

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

3 Comments

Thanks Owen, but the input fields are added at the end of the page. Is there a way to add it right below the clicked item
service_item_id is coming as null, is there a way to replicate it in the insert function. Thanks in advance for you help
@Exsite see the updated insert function()
0

I think you want to do something like

(this.myForm.controls as FormArray).push(this.fb.control(/*your item*/)

And the same for remove

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.