Luzan Baral
Luzan Baral

Reputation: 3698

Angular 10: Dynamically add input element for nested FormArray inside FormBuilder

Here's the link to my StackBlitz Demo App

I am trying to dynamically add input fields using FormBuilder array() method.

To get a clear vision look at my ngOnInit() and dependent methods

stackForm: FormGroup;

get work(): FormArray {
  return this.stackForm.get('work') as FormArray;
}

get highlights(): FormArray {
  return this.stackForm.get('work.highlights') as FormArray;
}

ngOnInit() {
    this.stackForm = new FormGroup({
        'work': this.fb.array([this.buildWork()])
    })        
}      

buildWork(): FormGroup {
    return this.fb.group({
        company: '',
        position: '',
        summary: '',
        highlights: this.fb.array([this.buildHighlights()])
    });
}

buildHighlights(): FormControl {
    return new FormControl()
}

HTML implementation is like this:

<div formArrayName="highlights">
    <div [formGroupName]="j"
          *ngFor="let hg of highlights.controls; let j=index">
     <!-- input element -->
    </div>
</div>

But I am getting this error message on console, and my input fields are not shown.

ERROR Error: ctx_r0.highlights is null

UPDATE: Thanks to @Lotte-Lemmens, helped me figure out the null issue. However, I cannot see a textbox on load. Maybe because it was null, how may I pass an empty value from the component so that it loops for once and I can see the textbox as well.

UPDATE: Thanks to @Eldar, I am able to see the textbox now, and add more for new highlights. On the Updated StackBlitz, there's still problem updating value of stackForm when hightlight is added. When I click on new highlight and add new highlight, the value is not added inside the highlights array in stackForm.value, only the first value is added.

But if i edit the first highlight (to recreate this issue, add multiple highlights first), all others are added into array at once.

Thanks.

Upvotes: 4

Views: 1237

Answers (2)

Eldar
Eldar

Reputation: 10790

Well, you need a few things to fix :

  1. Reaching the FormArray
 <div [formGroupName]="j" *ngFor="let hg of highlights(i); let j=index">

Since you are accessing a Form Array (work is a FormArray) you need to access the correct form array item. For this you need to use an index like above.

  1. To achieve goal 1. you need to change your highlights property into a function that accepts an index :
highlights(i :number): Array<FormControl> {
    let c =((this.stackForm.get('work') as FormArray).controls[i].get('highlights') as FormArray).controls as Array<FormControl>;
    return c;
}
  1. And finally you can directly bind formControl instead using formControlName
<input class="form-control"
                              id="{{'highlightsId' + j}}"
                              type="text"
                              placeholder="Highlights"
                              [formControl]="hg">

Edit: For adding new highlights you need to change your method like below :

 addHighlights(i = 0): void {
    this.highLightFormArray(i).push(this.buildHighlights());
  }

StackBlitz

Upvotes: 1

Lotte Lemmens
Lotte Lemmens

Reputation: 581

In the stackblitz you made, thanks for that, I can add a question mark toyour ngFor items. This solves the error on stackblitz

"let w of work?.controls; let i=index"
"let hg of highlights?.controls; let j=index"

This will first check if work/highlights exist, then loop over the controls. I'm not sure if this is your issue, but I hope it is...

Upvotes: 1

Related Questions