3

我认为这可能是 Reactive Form 的错误。我会感谢更有经验的 Angular 专家的任何帮助。

症状:在给定时间无法在输入中键入超过 1 个字符。

发生:当输入是 FormArray 中的 FormArray 时

我包含了一个 Plunker 链接,如下所示: https ://embed.plnkr.co/zl2BQe/ 。

//app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { ReactiveFormsModule } from '@angular/forms';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    ReactiveFormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
 })
export class AppModule { }

//app.component.ts
import { Component, OnInit} from '@angular/core';
import { FormArray, FormControl, FormGroup } from '@angular/forms';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {

  testForm: FormGroup; 

  ngOnInit(){
   this.testForm = new FormGroup({
   'lines': new FormArray([
    new FormGroup({
      'fields': new FormArray([
        new FormControl('')
      ])
     })
    ])
   })
  }

onAddLine(){
if(this.testForm.value.lines.length<10){
  (<FormArray>this.testForm.get('lines')).push(
    new FormGroup({
      'fields': new FormArray([
        new FormControl()
      ])
     })
   )
 }
}

onAddField(){
  // Not developed       
 }
}

//app.component.html
<div class="panel panel-default">
  <div class="panel-heading">
    Angular Reactive FormArray Error 
    <!--<button class="btn btn-primary" (click)="onAddField()">Add 
    Field</button>-->
    <button class="btn btn-primary" (click)="onAddLine()">Add 
    Line</button>
  </div>
<div class="panel-body">
  <form [formGroup]="testForm">
    <div class="form-inline" *ngFor="let line of testForm.value.lines; let i = index" formArrayName="lines">
      <div class="form-group">
        <span [formGroupName]="i">
          <span *ngFor="let field of testForm.value.lines[0].fields; let j = index" formArrayName="fields">
              <input type="text" class="form-control" [formControlName]="j">
              Please Type on Input Field
          </span>
        </span>
      </div>
    </div>
  </form>
</div>

4

1 回答 1

6

原因

您会遇到此问题,因为您依赖于formGroup.value在任何输入值更改时获取新实例。因此,您的控制树将在 DOM 中重新创建,从而失去焦点。

产生此问题的步骤是:

  • 您将直接反映该值的输入更改为该 FormControl
  • formGroup.value变化_
  • *ngFor迭代新值并创建新元素删除旧元素
  • 新元素将具有先前的元素值但没有焦点

为什么 *ngFor 创建新元素

NgFor创建新元素,因为trackBy默认情况下它是枚举值。如果值发生变化,则由旧值跟踪的来自 DOM 的元素被认为是过时的,因此被删除,并为新值创建一个新元素。即使值看起来相同,但它不是,只是 的另一个实例FormControl,因为您实际上是在枚举FormControls。

在您的情况下: *ngFor="let line of testForm.value.lines;... 并且 *ngFor="let field of testForm.value.lines[0].fields;... 因此不正确。

解决方案

这是一个更新的 Plunker

因此模板应如下所示:

  <div class="panel panel-default">
    <div class="panel-heading">
      Angular Reactive FormArray Error 
      <!--<button class="btn btn-primary" (click)="onAddField()">Add Field</button>-->
      <button class="btn btn-primary" (click)="onAddLine()">Add Line</button>
    </div>
    <div class="panel-body">
      <form [formGroup]="testForm">
        <div class="form-inline" *ngFor="let line of testForm.get('lines').controls; let i = index" formArrayName="lines">
          <div class="form-group">
            <span [formGroupName]="i">
              <span *ngFor="let field of line.get('fields').controls; let j = index" formArrayName="fields">
                  <input type="text" class="form-control" [formControlName]="j">
                  Please Type on Input Field
              </span>
            </span>
          </div>
        </div>
      </form>
    </div>
  </div>
于 2017-06-21T13:40:26.317 回答