Angular 2 Form“找不到带有路径的控件”

Posted

技术标签:

【中文标题】Angular 2 Form“找不到带有路径的控件”【英文标题】:Angular 2 Form "Cannot find control with path" 【发布时间】:2017-02-02 10:15:57 【问题描述】:

我尝试制作一个动态表单(这样您就可以无限制地将项目添加到列表中),但不知何故,我的列表内容没有被发送,因为它找不到带有路径的控件:

找不到带有路径的控件:'list_items -> list_item'

我的组件:

@Component(
  selector: 'app-list',
  templateUrl: './list.component.html',
  styleUrls: ['./list.component.css']
)
export class ListComponent implements OnInit 

  listForm: FormGroup;

  constructor(private nodeService: NodeService, private messageService: MessageService, private fb: FormBuilder,
                private listService: ListService)  
    this.listForm = this.fb.group(
      title: ['', [Validators.required, Validators.minLength(5)]],
      list_items: this.fb.array([
        this.initListItem(),
        ])
    );
  


  initListItem() 
    return this.fb.group(
      list_item: ['']
    );
  
  initListItemType() 
    return this.fb.group(
      list_item_type: ['']
    );
  

  addListItem() 
    const control = <FormArray>this.listForm.controls['list_items'];
    control.push(this.initListItem());
  

模板(list.component.html):

<h2>Add List </h2>

<form [formGroup]="listForm" novalidate (ngSubmit)="addList(listForm)">
  <div class="form-group">
    <input type="text" class="form-control" formControlName="title" placeholder="Title">
  </div>

  <div formArrayName="list_items">
    <div *ngFor="let list_item of listForm.controls.list_items.controls; let i=index" class="panel panel-default">
      i + 1.) <input type="text" formControlName="list_item" placeholder="List Item" class="form-control">
    </div>
    <a (click)="addListItem()">Add List Item +</a>

  </div>

  <button type="submit">Submit</button>
</form>

标题工作正常,但我找不到导致错误的“formControlName”错误。

在此先感谢您对此问题的任何帮助。

更新我所做的更改 list.component.html

<h2>Add List </h2>

<form [formGroup]="listForm" novalidate (ngSubmit)="addList(listForm)">
  <div class="form-group">
    <input type="text" class="form-control" formControlName="title" placeholder="Title">
  </div>

  <div formArrayName="list_items">
    <div *ngFor="let list_item of listForm.controls.list_items.controls; let i=index" class="panel panel-default">
      i + 1.) <input type="text" formControlName="i" placeholder="List Item" class="form-control">
    </div>
    <a (click)="addListItem()">Add List Item +</a>

  </div>

  <button type="submit">Submit</button>
</form>

在我的组件中,我更改了构造函数和 addListItem 方法:

listForm: FormGroup;

  constructor(private nodeService: NodeService, private messageService: MessageService, private fb: FormBuilder,
                private listService: ListService)  
    this.listForm = this.fb.group(
      title: ['', [Validators.required, Validators.minLength(5)]],
      list_items: this.fb.array([
          [''],
        ])
    );
  

  addListItem() 
    const control = <FormArray>this.listForm.controls['list_items'];
    control.push(this.fb.control(['']));
    console.log(control)
  

【问题讨论】:

【参考方案1】:

在您的 HTML 表单中应该有一个 formControlName 映射到您的组件文件。

<div *ngFor="let list_item of [0,1,2]; let i=index" class="panel panel-default">
  i + 1.) <input type="text" formControlName="i" placeholder="List Item" class="form-control">
</div>
list_items: this.fb.array([
    [''], //0 points to this
    [''], //1 points to this
    [''] //2 points to this
])

【讨论】:

这不会干扰我试图实现的目标吗?我有我的“initListItem()”,它返回“list_item”,因此可以动态添加新表单。您对如何实现这一点还有其他建议吗? 非常感谢您带领我朝着正确的方向前进。我将在主帖中发布我所做的更改:)! @dowu 那真是太棒了:) 更新了我在帖子中所做的更改;)! @Manish 如果我希望我的formControlName 更具描述性(如item-i),我将如何在formbuilder 数组中匹配它?可能吗?我尝试将[''] 替换为'item-0': '' 以及其他一些东西,但没有奏效,我找不到这样的示例。【参考方案2】:

我也遇到了这个错误,我通过初始化class(this.fb.array([])中的元素)的变量解决了这个问题。

代码片段

    mobileNumbers: this.fb.array([this.fb.group(new MobileNumber('IN'))]),

使用 MobileNumber 类的地方。

export class MobileNumber
    public country_code: string;
    public mobile_number: string;
    constructor($cc)
        this.country_code = COUNTRY_CODES[$cc];
    

export class MobileNumber
    public country_code = '';
    public mobile_number = '';
    constructor($cc)
        this.country_code = COUNTRY_CODES[$cc];
    

【讨论】:

【参考方案3】:

请注意,如果您的 FormArray 包含其他 FormGroup 控件(其中包含 FormControl 的其他实例),您需要执行此操作才能访问每个 FormGroup 中的控件:

        <div *ngFor="let item of myFormArray.controls; let i=index">
            <div formGroupName="i">
                <input formControlName="myFormGroupSubControl1" />
                <input formControlName="myFormGroupSubControl2" />

【讨论】:

我花了一个下午才知道 `[formGroupName]="i"` 是使用嵌套数组强制执行的。 谢谢您的好先生。这就是我所缺少的!!控件容器上的 formGroupName。 这很棘手,非常感谢为我节省了数小时的调试时间【参考方案4】:

FormArray@stackblitz 的简单示例(以下要点)

app.component.ts

import  Component,OnInit  from '@angular/core';
import  FormGroup, FormControl, FormArray, FormBuilder, Validators  from '@angular/forms';

@Component(
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
)
export class AppComponent implements OnInit 
  fg: FormGroup;
  constructor(private fb: FormBuilder)
  ngOnInit() 
  this.fg = this.fb.group(
    address: this.fb.group(
      street: ['', Validators.required],
    ),
    aliases: this.fb.array([])
  );
  const fa = (this.fg.get('aliases')as FormArray);
  this.addNewAlias();
  
  addNewAlias()
    const fa = (this.fg.get('aliases')as FormArray);
    fa.push(this.fb.group(
      name: ['', Validators.required]
    ));
  
  deleteAlias(i:number)
    const fa = (this.fg.get('aliases')as FormArray);
    fa.removeAt(i);
    if(fa.length===0) this.addNewAlias();
  

app.component.html

<form [formGroup]="fg" class="spaced">
  <h3>Nested in Group:</h3>
  <div formGroupName="address" class="spaced">
    <label>
      <input type="text" formControlName="street">
      valid: fg.get('address').get('street')?.valid
    </label>
  </div>
  <h3>Nested in Array:</h3>
  <div formArrayName="aliases" *ngFor="let alias of fg.get('aliases').controls; let i = index;" class="border">
    <div [formGroupName]="i">
      <label>
        Alias i+1:
        <input formControlName="name" placeholder="Item name">valid: alias.get('name')?.valid
      </label>
      <button type="button" (click)="deleteAlias(i)">X</button>
    </div>
  </div>
  <button type="button" (click)="addNewAlias()">add</button>
</form>
<div>form valid: fg?.valid</div>

【讨论】:

formArrayName 这正是我想要的,谢谢【参考方案5】:

你必须使用插值。

代替:

    <div
      class="form-group"
      *ngFor="let hobbyControl of getControls(); let i = index">
      <input type="text" class="form-control" formControlName="i">
    </div>

您必须使用带有“formControlName”的插值:

    <div
      class="form-group"
      *ngFor="let hobbyControl of getControls(); let i = index">
      <input type="text" class="form-control" [formControlName]="i">
    </div>

如果您使用的是最新版本的 Angular,请确保在 TypeScript 文件中进行操作,而不是在网页中,如下面文件“app.component.ts”中所示:

  getControls() 
    return (<FormArray>this.signupForm.get('hobbies')).controls;
  

【讨论】:

【参考方案6】:

-> 在组件文件中添加FormArray

 //TO USE FormArray (set form1:any;)
 form1:any;

  hobbies: new FormArray([
     new FormControl()
  ])

-> 向/从爱好中添加/删除控件

 addHobbies()
   this.form1.get('hobbies').push(new FormControl());
 

removeHobbies(index:number)
   this.form1.get('hobbies').removeAt(index);

-> 模板文件

<div formArrayName="hobbies">
   <label for="hobbies">Hobbies</label>
   <div *ngFor="let hobby of form1.get('hobbies').controls;index as i">
    <input type='text' id="hobbies" class="form-control" placeholder="hobbies" [formControlName]="i">
    <button type="button" (click)="removeHobbies(i)">remove</button>
  </div>
  <button type="button (click)="addHobbies()">Add</button> 
 </div>

【讨论】:

以上是关于Angular 2 Form“找不到带有路径的控件”的主要内容,如果未能解决你的问题,请参考以下文章

ERROR 错误:找不到带有路径的控件

Angular 7:“找不到具有未指定名称属性的控件”

Angular 2 Form“找不到控件”

Angular 2.0、Typescript 和“FORM_DIRECTIVES”模块

[Angular2 Form] Use RxJS Streams with Angular 2 Forms

Angular Material 2 Form 不显示