Javascript 角度反应形式:生成复选框值数组?

Javascript 角度反应形式:生成复选框值数组?,javascript,angular,checkbox,angular2-forms,Javascript,Angular,Checkbox,Angular2 Forms,给定绑定到同一formControlName的复选框列表,如何生成绑定到formControl的复选框值数组,而不是简单地true/false 示例: <form [formGroup]="checkboxGroup"> <input type="checkbox" id="checkbox-1" value="value-1" formControlName="myValues" /> <input type="checkbox" id="chec

给定绑定到同一
formControlName
的复选框列表,如何生成绑定到
formControl
的复选框值数组,而不是简单地
true
/
false

示例:

<form [formGroup]="checkboxGroup">
    <input type="checkbox" id="checkbox-1" value="value-1" formControlName="myValues" />
    <input type="checkbox" id="checkbox-2" value="value-2" formControlName="myValues" />
    <input type="checkbox" id="checkbox-3" value="value-2" formControlName="myValues" />
</form>
true or false
['value-1', 'value-2', ...]
我希望它产生什么:

<form [formGroup]="checkboxGroup">
    <input type="checkbox" id="checkbox-1" value="value-1" formControlName="myValues" />
    <input type="checkbox" id="checkbox-2" value="value-2" formControlName="myValues" />
    <input type="checkbox" id="checkbox-3" value="value-2" formControlName="myValues" />
</form>
true or false
['value-1', 'value-2', ...]

模板部分:-

    <div class="form-group">
         <label for="options">Options:</label>
         <div *ngFor="let option of options">
            <label>
                <input type="checkbox"
                   name="options"
                   value="{{option.value}}"
                   [(ngModel)]="option.checked"
                                />
                  {{option.name}}
                  </label>
              </div>
              <br/>
         <button (click)="getselectedOptions()"  >Get Selected Items</button>
     </div>
        export class Angular2NgFor {

          constructor() {
             this.options = [
              {name:'OptionA', value:'first_opt', checked:true},
              {name:'OptionB', value:'second_opt', checked:false},
              {name:'OptionC', value:'third_opt', checked:true}
             ];


             this.getselectedOptions = function() {
               alert(this.options
                  .filter(opt => opt.checked)
                  .map(opt => opt.value));
                }
             }

        }

这里是使用
FormArray

首先,我们将使用
FormBuilder
或新建
FormArray

FormBuilder

this.checkboxGroup = _fb.group({
  myValues: _fb.array([true, false, true])
});
新格式阵列

let checkboxArray = new FormArray([
  new FormControl(true),
  new FormControl(false),
  new FormControl(true)]);

this.checkboxGroup = _fb.group({
  myValues: checkboxArray
});
很容易做到,但接下来我们将更改模板,并让模板引擎处理如何绑定到控件:

template.html

<form [formGroup]="checkboxGroup">
    <input *ngFor="let control of checkboxGroup.controls['myValues'].controls"
    type="checkbox" id="checkbox-1" value="value-1" [formControl]="control" />     
  </form>
<form [formGroup]="form">
    <label *ngFor="let checkbox of checklistState" class="checkbox-control">
    <input type="checkbox" (change)="onChecklistChange($event.target.checked, checkbox)" [checked]="checkbox.checked" [value]="checkbox.value" /> {{ checkbox.label }}
  </label>
</form>

在这里,我们在
myValues
FormArray
中迭代
FormControls
集合,对于每个控件,我们将
[formControl]
绑定到该控件,而不是
FormArray
控件,
{checkboxGroup.controls['myValues'].value}
生成
true,false,true
,同时也减少了模板语法的手动性


您可以使用以下示例:为了在silentsod answer的帮助下浏览,我在formBuilder中编写了一个获取值而不是状态的解决方案

我使用一种方法在formArray中添加或删除值。这可能是一个糟糕的方法,但它是有效的

component.html

<div *ngFor="let choice of checks; let i=index" class="col-md-2">
  <label>
    <input type="checkbox" [value]="choice.value" (change)="onCheckChange($event)">
    {{choice.description}}
  </label>
</div>

只缺少一个功能,如果您的模型已经有检查值,则该功能将填充formArray。

单击它时生成一个事件,然后手动将true的值更改为复选框所代表的名称,然后名称或true将计算相同的值,您可以获得所有值,而不是true/false列表。例:

component.html

<form [formGroup]="customForm" (ngSubmit)="onSubmit()">
    <div class="form-group" *ngFor="let parameter of parameters"> <!--I iterate here to list all my checkboxes -->
        <label class="control-label" for="{{parameter.Title}}"> {{parameter.Title}} </label>
            <div class="checkbox">
              <input
                  type="checkbox"
                  id="{{parameter.Title}}"
                  formControlName="{{parameter.Title}}"
                  (change)="onCheckboxChange($event)"
                  > <!-- ^^THIS^^ is the important part -->
             </div>
      </div>
 </form>

在事件被角度形式更改为true或false后,它会捕获事件,如果是true,我会将名称更改为复选框所代表的名称,如果需要,也会在检查true/false时将其计算为true。

如果您正在寻找JSON格式的复选框值

{ "name": "", "countries": [ { "US": true }, { "Germany": true }, { "France": true } ] }

我很抱歉使用国家名称作为复选框值,而不是问题中的值。进一步解释-

为表单创建表单组

 createForm() {

    //Form Group for a Hero Form
    this.heroForm = this.fb.group({
      name: '',
      countries: this.fb.array([])
    });

    let countries=['US','Germany','France'];

    this.setCountries(countries);}
 }
让每个复选框都是一个FormGroup,它是从一个对象构建的,该对象的唯一属性是复选框的值

 setCountries(countries:string[]) {

    //One Form Group for one country
    const countriesFGs = countries.map(country =>{
            let obj={};obj[country]=true;
            return this.fb.group(obj)
    });

    const countryFormArray = this.fb.array(countriesFGs);
    this.heroForm.setControl('countries', countryFormArray);
  }
复选框的FormGroup数组用于设置父窗体中“国家”的控件

  get countries(): FormArray {
      return this.heroForm.get('countries') as FormArray;
  };
在模板中,使用管道获取复选框控件的名称

  <div formArrayName="countries" class="well well-lg">
      <div *ngFor="let country of countries.controls; let i=index" [formGroupName]="i" >
          <div *ngFor="let key of country.controls | mapToKeys" >
              <input type="checkbox" formControlName="{{key.key}}">{{key.key}}
          </div>
      </div>
  </div>

{{key.key}}
加上我的5美分) 我的问题模型

{
   name: "what_is_it",
   options:[
     {
      label: 'Option name',
      value: '1'
     },
     {
      label: 'Option name 2',
      value: '2'
     }
   ]
}
template.html

<div class="question"  formGroupName="{{ question.name }}">
<div *ngFor="let opt of question.options; index as i" class="question__answer" >
  <input 
    type="checkbox" id="{{question.name}}_{{i}}"
    [name]="question.name" class="hidden question__input" 
    [value]="opt.value" 
    [formControlName]="opt.label"
   >
  <label for="{{question.name}}_{{i}}" class="question__label question__label_checkbox">
      {{opt.label}}
  </label>
</div>

我的解决方案-使用材质视图解决角度5的问题
连接是通过

formArrayName=“通知”

(更改)=“UpdatechBxArray(n.id,$event.checked,'notification')”

通过这种方式,它可以在一种表单中用于多个复选框数组。 只需设置每次要连接的控件数组的名称

构造函数(
私人fb:FormBuilder,
私有http:http,
专用codeTableService:codeTableService){
this.codeTableService.getnotifications().subscribe(响应=>{
这是通知=响应;
})
...
}
createForm(){
this.form=this.fb.group({
通知:此.fb.array([])。。。
});
}
恩戈尼尼特(){
这个.createForm();
}
updateChkbxArray(id,已检查,密钥){
constchkarray=this.form.get(key);
如果(已检查){
chkArray.push(新表单控件(id));
}否则{
设idx=chkArray.controls.findIndex(x=>x.value==id);
chkArray.removeAt(idx);
}
}

要发送的通知:

{{n.description}}


在Angular 6中执行此操作比在以前的版本中要容易得多,即使复选框信息是从API异步填充的

首先要认识到的是,由于Angular 6的
keyvalue
管道,我们不再需要使用
FormArray
,而是可以嵌套
FormGroup

首先,将FormBuilder传递给构造函数

constructor(
    private _formBuilder: FormBuilder,
) { }
然后草签我们的表格

ngOnInit() {

    this.form = this._formBuilder.group({
        'checkboxes': this._formBuilder.group({}),
    });

}
当我们的复选框选项数据可用时,迭代它,我们可以将它作为命名的
FormControl
直接推送到嵌套的
FormGroup
中,而不必依赖数字索引的查找数组

const checkboxes = <FormGroup>this.form.get('checkboxes');
options.forEach((option: any) => {
    checkboxes.addControl(option.title, new FormControl(true));
});

如果要使用角度反应形式()

您可以使用一个表单控件来管理复选框组的输出值

组件

import { Component } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
import { flow } from 'lodash';
import { flatMap, filter } from 'lodash/fp';

@Component({
  selector: 'multi-checkbox',
  templateUrl: './multi-checkbox.layout.html',
})
export class MultiChecboxComponent  {

  checklistState = [ 
      {
        label: 'Frodo Baggins',
        value: 'frodo_baggins',
        checked: false
      },
      {
        label: 'Samwise Gamgee',
        value: 'samwise_gamgee',
        checked: true,
      },
      {
        label: 'Merry Brandybuck',
        value: 'merry_brandybuck',
        checked: false
      }
    ];

  form = new FormGroup({
    checklist : new FormControl(this.flattenValues(this.checklistState)),
  });


  checklist = this.form.get('checklist');

  onChecklistChange(checked, checkbox) {
    checkbox.checked = checked;
    this.checklist.setValue(this.flattenValues(this.checklistState));
  }

  flattenValues(checkboxes) {
    const flattenedValues = flow([
      filter(checkbox => checkbox.checked),
      flatMap(checkbox => checkbox.value )
    ])(checkboxes)
    return flattenedValues.join(',');
  }
}
html

<form [formGroup]="checkboxGroup">
    <input *ngFor="let control of checkboxGroup.controls['myValues'].controls"
    type="checkbox" id="checkbox-1" value="value-1" [formControl]="control" />     
  </form>
<form [formGroup]="form">
    <label *ngFor="let checkbox of checklistState" class="checkbox-control">
    <input type="checkbox" (change)="onChecklistChange($event.target.checked, checkbox)" [checked]="checkbox.checked" [value]="checkbox.value" /> {{ checkbox.label }}
  </label>
</form>
检查表
表单控制 此控件存储要另存为的值,例如

值输出:
“值1,值2”

参见TL上的演示;博士

  • 我更喜欢使用FormGroup填充复选框列表
  • 编写自定义验证器以进行检查至少选中了一个复选框
  • 工作示例

  • 这也让我有时感到震惊,所以我尝试了FormArray和FormGroup两种方法

    大多数时候,复选框列表是在服务器上填充的,我通过API收到它。但有时您会有一组带有预定义值的静态复选框。对于每个用例,将使用相应的FormArray或FormGroup

    基本上,
    FormArray
    FormGroup
    的一个变体。关键区别在于它的数据被序列化为数组(而不是在FormGroup中被序列化为对象)。当您不知道组中有多少控件(如动态表单)时,这可能特别有用

    对于t
    {
       label: 'Value 1',
       value: 'value_1',
       checked: false
    },
    {
      label: 'Samwise Gamgee',
      value: 'samwise_gamgee',
      checked: true,
    },
    {
      label: 'Merry Brandybuck',
      value: 'merry_brandybuck',
      checked: false
    }
    
    this.form = this.formBuilder.group({
        name: ["", Validators.required]
    });
    
    this.getCategories().subscribe(categories => {
        this.form.addControl("categoriesFormArr", this.buildCategoryFormArr(categories));
        this.form.addControl("categoriesFormGroup", this.buildCategoryFormGroup(categories));
    })
    
      buildCategoryFormArr(categories: ProductCategory[], selectedCategoryIds: string[] = []): FormArray {
        const controlArr = categories.map(category => {
          let isSelected = selectedCategoryIds.some(id => id === category.id);
          return this.formBuilder.control(isSelected);
        })
        return this.formBuilder.array(controlArr, atLeastOneCheckboxCheckedValidator())
      }
    
    get categoriesFormArraySelectedIds(): string[] {
      return this.categories
      .filter((cat, catIdx) => this.categoriesFormArr.controls.some((control, controlIdx) => catIdx === controlIdx && control.value))
      .map(cat => cat.id);
    }
    
    buildCategoryFormGroup(categories: ProductCategory[], selectedCategoryIds: string[] = []): FormGroup {
      let group = this.formBuilder.group({}, {
        validators: atLeastOneCheckboxCheckedValidator()
      });
      categories.forEach(category => {
        let isSelected = selectedCategoryIds.some(id => id === category.id);
        group.addControl(category.id, this.formBuilder.control(isSelected));
      })
      return group;
    }
    
    {
        "category1": false,
        "category2": true,
        "category3": true,
    }
    
      get categoriesFormGroupSelectedIds(): string[] {
        let ids: string[] = [];
        for (var key in this.categoriesFormGroup.controls) {
          if (this.categoriesFormGroup.controls[key].value) {
            ids.push(key);
          }
          else {
            ids = ids.filter(id => id !== key);
          }
        }
        return ids;
      }
    
    export function atLeastOneCheckboxCheckedValidator(minRequired = 1): ValidatorFn {
      return function validate(formGroup: FormGroup) {
        let checked = 0;
    
        Object.keys(formGroup.controls).forEach(key => {
          const control = formGroup.controls[key];
    
          if (control.value === true) {
            checked++;
          }
        });
    
        if (checked < minRequired) {
          return {
            requireCheckboxToBeChecked: true,
          };
        }
    
        return null;
      };
    }
    
    options: options[] = [{id: 1, text: option1}, {id: 2, text: option2}];
    
    this.fb.group({
      options: this.fb.array([])
    })    
    
    populateFormArray() {    
      this.options.forEach(option => {                       
        let checked = ***is checked logic here***;            
        this.checkboxGroup.get('options').push(this.createOptionGroup(option, checked))
      });       
    }  
    
    createOptionGroup(option: Option, checked: boolean) {
      return this.fb.group({      
        option: this.fb.control(option),
        checked: this.fb.control(checked)
      });
    }
    
    <form [formGroup]="checkboxGroup">
      <div formArrayName="options" *ngFor="let option of options; index as i">   
        <div [formGroupName]="i">
          <input type="checkbox" formControlName="checked" />
          {{ option.text }}
        </div>
      </div>       
    </form>
    
     this.checkboxGroup.get('options').value.filter(el => el.checked).map(el => el.option);