无法在响应式表单的 FormArray 内的 FormArray 输入中键入 1 个以上的字符 [英] Unable to typing more than 1 character in input for FormArray within a FormArray for Reactive Forms

查看:18
本文介绍了无法在响应式表单的 FormArray 内的 FormArray 输入中键入 1 个以上的字符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为这可能是 Reactive Form 的一个错误.如果能得到更有经验的 Angular 专家的帮助,我将不胜感激.

现象:在指定时间内无法输入超过 1 个字符.

出现:当输入是 FormArray 中的 FormArray 时

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

//app.module.ts从'@angular/platform-b​​rowser' 导入 { BrowserModule };从'@angular/core' 导入 { NgModule };从'@angular/forms'导入{ReactiveFormsModule};从 './app.component' 导入 { AppComponent };@NgModule({声明: [应用组件],进口:[浏览器模块,响应式表单模块],提供者:[],引导程序:[AppComponent]})导出类 AppModule { }//app.component.ts从@angular/core"导入{组件,OnInit};导入 { FormArray, FormControl, FormGroup } from '@angular/forms';@成分({选择器:'app-root',templateUrl: './app.component.html',styleUrls: ['./app.component.css']})导出类 AppComponent 实现 OnInit {testForm:FormGroup;ngOnInit(){this.testForm = new FormGroup({'行':新的FormArray([新表单组({'字段':新的FormArray([new FormControl('')])})])})}onAddLine(){if(this.testForm.value.lines.length<10){(<FormArray>this.testForm.get('lines')).push(新表单组({'字段':新的FormArray([新的表单控件()])}))}}onAddField(){//未开发}}//app.component.html<div class="panel panel-default"><div class="panel-heading">Angular Reactive FormArray 错误<!--<button class="btn btn-primary" (click)="onAddField()">添加字段</button>--><button class="btn btn-primary" (click)="onAddLine()">添加线

<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">请在输入字段中输入</span></span>

</表单>

解决方案

原因

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

产生这个问题的步骤是:

为什么 *ngFor 创建新元素

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

在你的情况下:*ngFor="let line of testForm.value.lines;...*ngFor="let field of testForm.value.lines[0].fields;...由于这个原因是不正确的.

解决方案

这是一个更新的 Plunker.

因此模板应如下所示:

 

<div class="panel-heading">Angular Reactive FormArray 错误<!--<button class="btn btn-primary" (click)="onAddField()">添加字段</button>--><button class="btn btn-primary" (click)="onAddLine()">添加行</button>

<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">请在输入字段中输入</span></span>

</表单>

I am thinking this could be a bug for Reactive Form. I would appreciate any help from more experienced Angular Experts.

Symptom: Unable to key in more than 1 character in input at given time.

Occurrence: When input is a FormArray within a FormArray

I have included a Plunker link as below: 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>

解决方案

Cause

You get this problem because you rely on formGroup.value which gets a new instance when any of the input value changes. Therefore your control tree will be recreated in DOM thus loosing the focus.

The steps which create this problem are:

Why *ngFor creates new elements

NgFor creates new elements because of trackBy which is by default the enumerated value. If the value changes, the element from DOM, which is tracked by the older value, is considered to be obsolete, thus being removed, and a new element is created for the new value. Even if the value appears to be the same, it is not, is just another instance of FormControl, as you are actually enumerating over the FormControls.

In your case: *ngFor="let line of testForm.value.lines;... and *ngFor="let field of testForm.value.lines[0].fields;... are incorrect for this reason.

Solution

Here is an updated Plunker.

Therefore the template should look like:

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

这篇关于无法在响应式表单的 FormArray 内的 FormArray 输入中键入 1 个以上的字符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆