【问题标题】:Angular 5 Reactive Forms - pass checkbox Id's for FormArrayAngular 5 Reactive Forms - 为 FormArray 传递复选框 ID
【发布时间】:2018-09-06 05:16:37
【问题描述】:

我正在使用响应式表单 FormGroup、FormBuilder 和 FormArray。我有一个 FormArray,我想在其中循环一个外部数组,创建一个复选框列表,然后将这些复选框的 id 传递给我的 FormArray。

我的组件打字稿看起来像:

export class AppComponent  {
  form: FormGroup;

  sites = [ "site-1", "site-2", "site-3", "site-4" ];

  constructor(private fb: FormBuilder){ 
  }

  ngOnInit() {
    this.form = this.fb.group({
      type: [ '', Validators.required ],
      sites: this.fb.array([
        this.fb.group({
          siteId: [ '', Validators.required ]
        })
      ])
    })
  }
}

还有我的html...

<form [formGroup]="form">

  <input type="checkbox" formControlName="type" id="type">
  <label for="type">Type</label>

  <div class="checkbox-group" style="margin-top:40px">
      <div class="checkbox-wrap" id="productsContainer">
          <input type="checkbox" id="all">
          <label for="all">All mills</label>
          <div *ngFor="let site of sites; let i = index">
              <input type="checkbox" [id]="i" /> 
              <label [for]="i"> {{ site }} </label>
          </div>
      </div>
  </div>
</form>

我知道我需要将 formArrayName 传递到 html 中,但在尝试传递 formArrayName="sites" 然后使用循环中的“i”作为 formGroupName 时出现控制台错误。我做错了什么?

这是一个完整设置的 StackBlitz...

https://stackblitz.com/edit/angular-rcfnwi?file=app%2Fapp.component.html

【问题讨论】:

标签: arrays angular typescript angular5 angular-reactive-forms


【解决方案1】:

答案确实有效,但是,在我看来,它显然不是一个表单数组。 当我们进行一系列检查时,我们必须了解有两个独立的概念:表单和数据。是的,这两个概念不一定相等。

我选择像这样创建表单

//we create a FormGroup array transform the array "this.sites"
const controls:FormGroup[]=this.sites.map(x=>{
  return this.fb.group({
    site:false
  })
});
//in this.form I use this array of FormGroup
this.form = this.fb.group({
  type: ['', Validators.required],
  sites: this.fb.array(controls)
})

嗯,当我们制作表单时,form.value 可以是这样的

{
  "type": "", 
  "sites": [ 
    { "site": false }, { "site": true }, { "site": false }, { "site": true }
  ]
} 

然后,在提交时,我们必须将 form.value 转换为我们喜欢的数据

  submit(form: FormGroup) {
    if (form.valid) {
      //create an array of sites
      let sites: string[] = [];
      let i: number = 0;
      form.value.sites.forEach((x:any) => {
        if (x.site)
          sites.push(this.sites[i]);
        i++;
      });
      //Our data will be
      let data = {
        type: form.value.type,
        sites: sites
      }
      console.log(data);
    }
  }

最后是表格:

<form [formGroup]="form" (submit)="submit(form)" novalidate">
<input formControlName="type">
  <div formArrayName="sites" *ngFor="let site of form?.get('sites').controls;let i=index">
    <div [formGroupName]="i">
      <--!see that formControlName is "site"
      and the labels of the check use the array this.sites -->
      <input type="checkbox" formControlName="site" /> {{sites[i]}}
    </div>
  </div>
  <button>send</button>
</form>

所有人都在问为什么在地球上,它是什么?所有的事情一定太复杂了?我的回答是它没有那么复杂。此外,想象一下如何用数据填充表单。

//if data={type:"a",sites:["site-2","site-4"], we create the form like
const controls:FormGroup[]=this.sites.map(x=>{
  return this.fb.group({
    site:data.sites.indexOf(x)>=0; //true or false
  })
});
this.form = this.fb.group({
  type: [data.type, Validators.required],
  sites: this.fb.array(controls)
})

【讨论】:

    【解决方案2】:

    您需要使用与站点列表中的项目相对应的各个 FormControl 来填充 FormArray。在我的 fork 示例中,我在 FormGroup (https://stackblitz.com/edit/angular-hilz9h) 的初始化中通过映射站点数组并生成默认值为 false(未选中)的 FormControls 来执行此操作。我还删除了围绕站点 FormArray 的嵌入式 FormGroup 以使其更简单。然后,我将 formArrayName 指令添加到包装 div 中,其字符串属性对应于 ts 文件中 FormArray 的“站点”名称。最后,我添加了一个 [formControlName] 指令并将每个输入的 ngFor 索引传递给它,以对应于 FormArray 控件的数组索引。 FormArrays 在内部通过索引跟踪它们的控件。

    所以,您的 ngOnInit 现在看起来像:

    ngOnInit() {
        this.form = this.fb.group({
          type: [ '', Validators.required ],
          sites: this.fb.array(this.sites.map(s => this.fb.control(false)),
              [ Validators.required ])
        })
      }
    

    你的 html 文件现在看起来像:

    <form [formGroup]="form">
    
      <input type="checkbox" formControlName="type" id="type">
      <label for="type">Type</label>
    
      <div class="checkbox-group" style="margin-top:40px">
          <div class="checkbox-wrap" id="productsContainer" formArrayName="sites">
              <input type="checkbox" id="all">
              <label for="all">All mills</label>
              <div *ngFor="let site of sites; let i = index">
                  <input type="checkbox" [id]="i" [formControlName]="i"/> 
                  <label [for]="i"> {{ site }} </label>
              </div>
          </div>
      </div>
    </form>
    
    <pre> {{ form.value | json }}</pre>
    

    【讨论】:

      猜你喜欢
      • 2020-07-24
      • 2022-12-27
      • 1970-01-01
      • 2023-04-06
      • 2018-10-13
      • 1970-01-01
      • 2018-01-26
      • 2021-04-28
      • 2019-10-30
      相关资源
      最近更新 更多