首页 文章

Angular 5 Reactive Forms - 为FormArray传递复选框Id

提问于
浏览
0

我正在使用Reactive Forms 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

2 回答

  • 1

    您需要使用与站点列表中的项目对应的单个FormControl填充FormArray . 在我的fork示例中,我在FormGroup(https://stackblitz.com/edit/angular-hilz9h)的初始化中通过映射站点数组并生成默认值为false(未选中)的FormControl来完成此操作 . 我还删除了围绕站点FormArray的嵌入式FormGroup,使其更简单 . 然后我将formArrayName指令添加到包装div中,其字符串属性对应于ts文件中FormArray的'sites'名称 . 最后,我添加了一个[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>
    
  • 0

    答案真的很有用,但是,在我看来并不是一个Form Array . 当我们有一系列检查时,我们必须理解有两个独立的概念:形式和数据 . 是的,这两个概念不是必要的 .

    我选择创建表单

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

相关问题