代码之家  ›  专栏  ›  技术社区  ›  JordanBarber

角度5反应形式-传递FormArray的复选框Id

  •  1
  • JordanBarber  · 技术社区  · 7 年前

    我正在使用反应式表单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 回复  |  直到 7 年前
        1
  •  3
  •   TonyM    6 年前

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

    因此,您的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>
    
        2
  •  -1
  •   monstertjie_za    5 年前

    答案确实有用,但在我看来,并不是一个清晰的表单数组。 当我们有一系列的检查时,我们必须理解有两个独立的概念:表单和数据。是的,这两个概念并不一定相等。

    我选择创建如下表单

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

    嗯,当我们制作表单时,表单。值可以是

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

    然后,在提交中,我们必须转换形式。我们喜欢的数据的价值

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