So I have a FormArray containing FormGroups with 3 controls. Visually it looks like a table with 3 inputs on each row. Here is how it looks:
I want when the user presses tab or enter at the last input in the row - a new empty row to be added after it. So I added (keydown)="addRow($event.keyCode, i)"
to the last input and created the function:
public addRow(keyCode, index)
{
if (keyCode !== 9 && keyCode !== 13) {
return;
}
let formItems = this.form.get('items') as FormArray;
formItems.insert(
index + 1,
this.formBuilder.group({
'start': ['', Validators.required],
'title': ['', Validators.required],
'category': [''],
})
);
}
Afther the FormGroup is pushed, I can see the controls correctly in the form array, however the view is updated strangely. After for example I press tab on the last input in the first row I get this result:
Last row is removed and I get two empty rows in the after the first. I couldn't find out why. Here is the FormArray after the push, the items are OK there:
Here is the view code:
<div formArrayName="items">
<div *ngFor="let item of form.controls.items.controls; let i=index" [formGroupName]="i" class="row item-index-{{ i }}">
<div class="form-group">
<div class="col-sm-2">
<input type="text" class="form-control" placeholder="Start" autocomplete="off" formControlName="start">
</div>
<div class="col-sm-4">
<input type="text" class="form-control" placeholder="Title" autocomplete="off" formControlName="title">
</div>
<div class="col-sm-4">
<input type="text" class="form-control" placeholder="Category" autocomplete="off" formControlName="category" (keydown)="addRow($event.keyCode, i)">
</div>
<div class="col-sm-2">
<a class="btn btn-icon-only default">
<i class="fa fa-arrow-up"></i>
</a>
<a class="btn btn-icon-only default">
<i class="fa fa-arrow-down"></i>
</a>
<a class="btn btn-icon-only red">
<i class="fa fa-times"></i>
</a>
</div>
</div>
</div>
</div>
Any idea why this happens?
So I have a FormArray containing FormGroups with 3 controls. Visually it looks like a table with 3 inputs on each row. Here is how it looks:
I want when the user presses tab or enter at the last input in the row - a new empty row to be added after it. So I added (keydown)="addRow($event.keyCode, i)"
to the last input and created the function:
public addRow(keyCode, index)
{
if (keyCode !== 9 && keyCode !== 13) {
return;
}
let formItems = this.form.get('items') as FormArray;
formItems.insert(
index + 1,
this.formBuilder.group({
'start': ['', Validators.required],
'title': ['', Validators.required],
'category': [''],
})
);
}
Afther the FormGroup is pushed, I can see the controls correctly in the form array, however the view is updated strangely. After for example I press tab on the last input in the first row I get this result:
Last row is removed and I get two empty rows in the after the first. I couldn't find out why. Here is the FormArray after the push, the items are OK there:
Here is the view code:
<div formArrayName="items">
<div *ngFor="let item of form.controls.items.controls; let i=index" [formGroupName]="i" class="row item-index-{{ i }}">
<div class="form-group">
<div class="col-sm-2">
<input type="text" class="form-control" placeholder="Start" autocomplete="off" formControlName="start">
</div>
<div class="col-sm-4">
<input type="text" class="form-control" placeholder="Title" autocomplete="off" formControlName="title">
</div>
<div class="col-sm-4">
<input type="text" class="form-control" placeholder="Category" autocomplete="off" formControlName="category" (keydown)="addRow($event.keyCode, i)">
</div>
<div class="col-sm-2">
<a class="btn btn-icon-only default">
<i class="fa fa-arrow-up"></i>
</a>
<a class="btn btn-icon-only default">
<i class="fa fa-arrow-down"></i>
</a>
<a class="btn btn-icon-only red">
<i class="fa fa-times"></i>
</a>
</div>
</div>
</div>
</div>
Any idea why this happens?
Share Improve this question asked Aug 2, 2017 at 8:51 vuryssvuryss 1,3008 silver badges17 bronze badges3 Answers
Reset to default 17In case someone has this problem but the cause is different, check if you're adding your controls correctly:
let arr = new FormArray([]);
arr.push(....); // Make sure you do this
arr.controls.push(....); // And not this!
I've encountered this issue once earlier when not inserting formgroup at the end of formarray. Seems Angular is having trouble tracking the index in template for some reason, and by using trackBy
solved it. So try:
<div *ngFor="let item of form.get('items').controls; let i=index; trackBy:trackByFn"
[formGroupName]="i" class="row item-index-{{ i }}">
and in TS:
trackByFn(index: any, item: any) {
return index;
}
For Angular 18 using the @for syntax
@for(item of form.get('items').controls;let i = $index; track item){
<div [formGroupName]="i" class="row item-index-{{ i }}">
}
Worked for me.