1

In my angular app trying to add a dynamic form group with two form controls in the form array, how can I be able to add form controls dynamically in here? I have tried to add like this way [formControlName]="i" but getting this Cannot find control with path: 'dinings -> 0 -> 0'.

If I add statically formControlName="name" and formControlName="cuisine" not getting the error but values in formcontrols are not updating after addition.

This is what I have done -

HTML

 <div>
     <form [formGroup]="diningForm" (ngSubmit)="addDiningDetails()">
       ....
       <div class="added-dining-list">
         <ul>
           <li formArrayName="dinings" *ngFor="let dining of dinings;let i = index">
            <div [formGroupName]="i">
              <input type="text" class="form-input" placeholder="Dining Name" [formControlName]="i" />
              <input type="text" class="form-input" placeholder="Dining Cuisine" [formControlName]="i" />
              <a href="#">Delete</a>
           </div>
        </li>
        <li>
           <form [formGroup]="diningInfoForm" class="dining-info-form">
              <input type="text" class="form-input" formControlName="diningName"/>
              <input type="text" class="form-input" formControlName="diningCuisine"/>
              <a href="#" (click)="addDining($event)">Add Dining</a>
           </form>
        </li>
      </ul>
    </div>
  </form>

TS

ngOnInit(){
  //Dining Form
    this.diningForm = this._formBuilder.group({
        isOfferingDining: new FormControl('', [Validators.required]),
        dinings: this._formBuilder.array([]),
        diningInfo: new FormControl('')
    });

  //Dining info add form
    this.diningInfoForm = this._formBuilder.group({
        diningName: new FormControl('', [Validators.required]),
        diningCuisine: new FormControl('', [Validators.required])
    });
}

//Adding single dining in form array
addDiningMenu(event: MouseEvent) {
    event.preventDefault();
    if (this.diningInfoForm.invalid) {
        this.showErrorMessages();
    }
    const formValue = this.diningInfoForm.value;
    const formGroup = this._formBuilder.group({
        name: new FormControl(formValue.diningName, [Validators.required]),
        cuisine: new FormControl(formValue.diningCuisine, [Validators.required])
    });
    this.dinings.push(formGroup);
}

//Final Submit of the form
addDiningDetails() {
    this._messageService.clear();
    if (this.diningForm.invalid) {
        this.showErrorMessages();
        return;
    }
    console.log(this.diningForm.value);
}

//Getting form array
get dinings() {
    return (this.diningForm.get('dinings') as FormArray).controls;
}

4 Answers 4

3

First things First, Can you nest forms? NO See Can you nest html forms?. Remove the nested form from your form

Next step is to have a picture of how you expect your object to be, We will produce a form that looks like below

{
   isOfferingDining: '',
   dinings: [
     {
        diningName: '',
        diningCuisine: ''
      },
      {
        diningName: '',
        diningCuisine: ''
      }
   ]
}

I am assuming that you have several dinings and each dining has a diningName and diningCuisine. Your form didn't do much in clarifying this

Change the getter dinings to return a FormArray

  //Getting form array
  get dinings() {
    return (this.diningForm.get('dinings') as FormArray);
  }

Now define the addDinings() and deleteDining() function

  addDining() {
    this.dinings.push(
      this._formBuilder.group({
        diningName: new FormControl('', [Validators.required]),
        diningCuisine: new FormControl('', [Validators.required])
      })
    );
  }
  deleteDining(i) {
    this.dinings.removeAt(i);
  }

Modify your html to match the form group

<form [formGroup]="diningForm" (ngSubmit)="addDiningDetails()">
  Is Offering Dining <input formControlName='isOfferingDining'>
  <div class="added-dining-list">
    <ul formArrayName="dinings">
      <li *ngFor="let dining of dinings.controls;let i = index" [formGroupName]="i">
        <input type="text" class="form-input" placeholder="Dining Name" formControlName="diningName" />
        <input type="text" class="form-input" placeholder="Dining Cuisine" formControlName="diningCuisine" />
        <a (click)="deleteDining(i)" href="#">Delete</a>
      </li>
    </ul>
    <a href="#" (click)="addDining()">Add Dining</a>
  </div>
  <button type="submit">Submit</button>
</form>

Now everything should work as expected

See Demo Here

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

Comments

0

You need to specify the right form control name:

        <li formArrayName="dinings" *ngFor="let dining of dinings;let i = index">
            <div [formGroupName]="i">
              <input type="text" class="form-input" placeholder="Dining Name" [formControlName]="dining.name" />
              <input type="text" class="form-input" placeholder="Dining Cuisine" [formControlName]="dining.cuisine" />
              <a href="#">Delete</a>
           </div>

2 Comments

I have already tried this got this - Cannot find control with path: 'dinings -> 0 -> '
You need to ensure that your form group array is initialized based on "dinings"
0

Try removing controls in get dinings().

//Getting form array
get dinings() {
    return this.diningForm.get('dinings') as FormArray;
}

Comments

0

@Rahul you can change your dinnings return FormArray instead of controls.

In component.ts file

get dinings() {
  return this.diningForm.get('dinings') as FormArray;
}

In component.html file

<li formArrayName="dinings">
<div *ngFor="let dining of dinings().controls; let i = index">
  <div [formGroupName]="i">
    <input type="text" class="form-input" placeholder="Dining Name" formControlName="name" />
    <input type="text" class="form-input" placeholder="Dining Cuisine" formControlName="cuisine" />
    <a href="#">Delete</a>
  </div>
</div>
</li>

Ref: FormArray Reference Link

2 Comments

with this approach controls, are adding, whenever I am changing any values in the controls always getting the old and default ones(Initial values when controls was created)
Please check this stackblitz.com/edit/angular-ivy-4gcwgl. If possible go through the reference link which was attached with the above answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.