最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Angular2 FormArray insert does not update view accordingly - Stack Overflow

programmeradmin4浏览0评论

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 badges
Add a comment  | 

3 Answers 3

Reset to default 17

In 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.

发布评论

评论列表(0)

  1. 暂无评论