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上的演示;博士
这也让我有时感到震惊,所以我尝试了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);