我想对我的复选框FormBuilder.array进行验证,但是尽管选中了其中一个复选框,但该表单仍然无效。
我已经尝试过Validators.required
和Validators.requiredTrue
,但仍然无法按预期运行
TS:
this.Form = this.fb.group({
stage: this.fb.array([], Validators.required)
})
HTML:
<div class="form-check-label">
<label class="checkbox-inline">
<input type="checkbox" class="checkbox" name="none" value="1" #noneChk
(change)="onCheckArray($event, Form.value.stage)">
Stage 1
</label>
</div>
<div class="form-check-label">
<label class="checkbox-inline">
<input type="checkbox" class="checkbox" name="self" value="2" #selfChk
(change)="onCheckArray($event, Form.value.stage)">
Stage 2
</label>
</div>
<p>{{ this.Form.valid | json }}</p>
我有我的StackBlitz here
答案 0 :(得分:1)
关于您的堆叠闪电战,我forked your stackblitz
问题在于您的函数onCheckArray不会更改FormArray(是的,您更改了值,但未更改FormArray,因此进行了任何验证。请参见编辑的函数
//I repite the getter stage, so the answer can be understood
get stage(): FormArray {
return this.Form.get('stage') as FormArray;
}
onCheckArray(event) { //you needn't send the value
/* Selected */
if (event.target.checked) {
// Add a new control in the arrayForm,
// use push, but add a new FormControl TO the formArray
this.stage.push(new FormControl(event.target.value));
} else {
/* unselected */
// find the unselected element
let i: number = 0;
//we iterate over the formArray
for (i = 0; i < this.stage.value.length; i++) {
if (this.stage.value[i] == event.target.value) {
//use removeAt(i)
this.stage.removeAt(i);
return;
}
}
}
}
好吧,您的函数验证器可以更简单,只需检查数组的长度即可
minSelectedCheckboxes(min = 1) {
return (formArray: FormArray) => {
return formArray.controls.length >= min ? null : { required: true };
};
}
如果初始化FormArray会出现问题
this.Form = this.fb.group({
stage: this.fb.array([new FormControl("3")], this.minSelectedCheckboxes())
})
您的.html必须像
<div class="form-check-label">
<label class="checkbox-inline">
<input type="checkbox" class="checkbox" name="none" value="1" #noneChk
<!--see how indicate when is checked-->
[checked]="stage.value.indexOf('1')>=0"
(change)="onCheckArray($event)">
1
</label>
</div>
嗯,我想问的是一种管理数组复选框的更简单方法,我们可以采取另一种方式。我们的FormArray将是一个值为true / false的控件数组,并且我们可以通过函数htht将该数组转换为我们的值。
options=["1","2","3","4"]; //our options
get valuesSelected() ; //a function that return the options selected
{
return this.options.filter((x,index)=>this.newForm.get('stage').value[index])
}
//see how create the formArray, always has the same number of
//elements that our options
this.newForm=new FormGroup({
stage:new FormArray(this.options
.map(x=>new FormControl(false)),this.minTrueCheckboxes())
})
minTrueCheckboxes(min = 1) {
return (formArray: FormArray) => {
return formArray.value.filter(x=>x).length>=min? null : { required: true };
};
}
我们的.html变得像
<form class="form" [formGroup]="newForm" (ngSubmit)="onSubmit()">
<div formArrayName="stage">
<label class="checkbox-inline" *ngFor="let control of newForm.get('stage').controls;let i=index">
<input type="checkbox" class="checkbox" [formControl]="control" >
{{options[i]}}
</label>
</div>
</form>
<p>{{ valuesSelected | json }}</p>
答案 1 :(得分:0)
可以在自己的组件中创建自定义验证器 或外面。
您可以在this stackblitz
中看到两个模型//In the own component
this.form = new FormGroup({
checks: new FormArray([
new FormControl(true),
new FormControl(false),
], this.AtLeatOne()), //sii that call it as this.AtLeastOne
});
AtLeatOne() {
return (control: FormArray) => {
if (control.value.find(x => x))
return null
return { "error": "You must select at least one option" }
}
}
//OutSide
this.form2 = new FormGroup({
checks: new FormArray([
new FormControl(true),
new FormControl(false),
], AtLeatOneValidator())
});
export function AtLeatOneValidator()
{
return (control: FormArray)=> {
if (control.value.find(x => x))
return null
return { "error": "You must select at least one option" }
}
}
好吧,如果要向函数发送参数(我想我们希望用户至少选择2个选项),我给出了最一般的例子。