简体   繁体   English

Angular 5 Reactive Forms-通过FormArray的复选框ID

[英]Angular 5 Reactive Forms - pass checkbox Id's for FormArray

I am using Reactive Forms FormGroup, FormBuilder and FormArray. 我正在使用反应形式FormGroup,FormBuilder和FormArray。 I have a FormArray in which I would like to loop through an external array, create a list of checkboxes and then pass the id of those checkboxes to my FormArray. 我有一个FormArray,我想在其中循环遍历一个外部数组,创建一个复选框列表,然后将这些复选框的ID传递给我的FormArray。

My components typescript looks like: 我的组件打字稿看起来像:

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 ]
        })
      ])
    })
  }
}

And my html... 还有我的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>

I know I need to pass the formArrayName into the html but I am getting console errors when trying to pass in the formArrayName="sites" and then using the "i" from my loop as the formGroupName. 我知道我需要将formArrayName传递到html中,但是在尝试传递formArrayName =“ sites”,然后将循环中的“ i”用作formGroupName时遇到控制台错误。 What am I doing wrong? 我究竟做错了什么?

Here's a StackBlitz with the full setup... 这是具有完整设置的StackBlitz ...

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

You need to populate the FormArray with the individual FormControls that correspond to the items in your sites list. 您需要使用与站点列表中的项目相对应的单个FormControl填充FormArray。 In my fork example, I did this in the initialization of the FormGroup ( https://stackblitz.com/edit/angular-hilz9h ) by mapping over the sites array and generating FormControls with a default value of false (unchecked). 在我的fork示例中,我在FormGroup( https://stackblitz.com/edit/angular-hilz9h )的初始化中通过映射sites数组并生成默认值为false(未选中)的FormControls进行了此操作。 I also removed the embedded FormGroup that was surrounding the sites FormArray to make it simpler. 我还删除了围绕站点FormArray的嵌入式FormGroup,以使其更加简单。 I then added the formArrayName directive to the wrapping div with the string attribute corresponding to the 'sites' name of the FormArray from the ts file. 然后,我使用与ts文件中FormArray的“站点”名称相对应的字符串属性,将formArrayName指令添加到包装div中。 Finally, I added a [formControlName] directive and passed it the ngFor index of each input to correspond to the array index of the FormArray controls. 最后,我添加了一个[formControlName]指令,并将每个输入的ngFor索引传递给它,以对应于FormArray控件的数组索引。 FormArrays internally keep track of their controls by index. FormArray在内部通过索引跟踪其控件。

So, your ngOnInit now looks like: 因此,您的ngOnInit现在看起来像:

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

and your html file now looks like: 现在您的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>

Really the answer work, but, in my opinion is not clearly a Form Array. 确实可以解决问题,但我认为显然不是Form Array。 When we have a serie of checks, we must to understand that there are two separate concept: the form and the data. 当我们进行一系列检查时,我们必须了解有两个独立的概念:表单和数据。 Yes this two concepts are not necesary equal. 是的,这两个概念不是必须相等的。

I choose create the form like 我选择创建像

//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)
})

Well, when we make the form, the form.value can be like 好,当我们制作表格时,form.value可以像

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

Then, in submit we must transform the form.value to a data we like 然后,在提交中,我们必须将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);
    }
  }

Finally, the form: 最后,形式:

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

All are asking Why on earth and What little shit is it? 所有人都在问为什么在地球上,到底是什么东西? All the things must be too complex? 所有的事情一定太复杂了吗? My answer is that it is not so complex. 我的回答是,它并不那么复杂。 FurtherMore, imagine how can populate the form with data. 此外,想象一下如何用数据填充表格。

//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)
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM