Angular Reactive Forms 自定义验证器最小和最大选中复选框
Angular Reactive Forms custom validator minimum and maximum checked checkboxes
我有一个 Angular 反应形式,人们 select 他们最喜欢的水果最少 1 种,最多 3 种。
模板:
<div>
<h3>Which maximum 3 fruits do you like best?</h3>
<form *ngIf="myForm" [formGroup]="myForm" (ngSubmit)="onSubmit(myForm.value)" novalidate>
<div *ngFor="let answer of answers.controls; let i=index">
<input type="checkbox" [formControl]="answer">{{fruits[i]}}<br>
</div>
<button type="submit" [disabled]="!myForm.valid">Submit</button>
</form>
</div>
组件:
export class AppComponent {
myForm: FormGroup;
fruits: Array<string> = ["apple", "pear", "kiwi", "banana", "grape", "strawberry", "grapefruit", "melon", "mango", "plum"];
constructor(private formBuilder: FormBuilder) { }
ngOnInit() {
this.myForm = this.formBuilder.group({}, {
validator: this.anotherValidator.bind(this)
});
let answersFormArray = this.fruits.map(fruit => { return this.formBuilder.control(false, [this.validateMaxCheckboxes.bind(this)]) });
this.myForm.setControl('answers', this.formBuilder.array(answersFormArray));
}
validateMaxCheckboxes(control: FormControl) {
return null;
};
anotherValidator(group: FormGroup) {
return null;
};
get answers(): FormArray {
return this.myForm.get('answers') as FormArray;
};
onSubmit(submit) {
console.log(submit.answers);
}
}
你最喜欢哪三种水果?然后会显示一个水果列表(复选框),用户可以 select。
我想要这种行为:
如果用户select什么都没有,提交按钮被禁用,至少需要select编辑1个水果。如果用户 select 吃了 1 或 2 个水果,则启用提交按钮。如果用户 select 是第 3 个水果(选中 3 个复选框),我想禁用所有未选中的水果,提交按钮保持启用状态。如果取消选中 3 个水果中的一个,则启用所有复选框。这样,用户可以从列表中 select 最少 1 个和最多 3 个水果。
我尝试了很多东西,在谷歌上搜索了很多,但我无法让它工作。
@ArunKumaresh 的答案也有效,但与我的原始代码相去甚远。但他为我指出了正确的方向,所以我可以想出这个解决方案:
模板:
<div>
<h3>Which maximum 3 fruits do you like best</h3>
<form *ngIf="myForm" [formGroup]="myForm" (ngSubmit)="onSubmit(myForm)" novalidate>
<div *ngFor="let answer of answers.controls; let i=index">
<input type="checkbox" [formControl]="answer" (change)="onChangeAnswer($event.target.checked)">{{fruits[i]}}<br>
</div>
<button type="submit" [disabled]="!myForm.valid">Submit</button>
</form>
</div>
组件:
export class AppComponent {
fruits: Array<string> = ["apple", "pear", "kiwi", "banana", "grape", "strawberry", "grapefruit", "melon", "mango", "plum"];
myForm: FormGroup;
numChecked: number = 0;
constructor(private formBuilder: FormBuilder) { }
ngOnInit() {
this.myForm = this.formBuilder.group({}, {
validator: this.minOneAnswer.bind(this)
});
let answersFormArray = this.fruits.map(fruit => { return this.formBuilder.control(false) });
this.myForm.setControl('answers', this.formBuilder.array(answersFormArray));
}
minOneAnswer(control) {
return this.numChecked === 0 ? { minOneAnswerChecked: true } : null;
}
onChangeAnswer(checked: boolean) {
checked ? this.numChecked++ : this.numChecked--;
const answerFormArray = this.myForm.get('answers') as FormArray;
if (this.numChecked >= 3) {
answerFormArray.controls.forEach((item) => {
if (!item.value) item.disable()
})
} else {
answerFormArray.controls.forEach((item) => {
if (!item.value) item.enable()
})
}
}
get answers(): FormArray {
return this.myForm.get('answers') as FormArray;
};
onSubmit(form: FormGroup) {
const answerFormArray = form.get('answers') as FormArray;
answerFormArray.controls.forEach((item) => {
if (!item.value) item.enable()
})
console.log(form.value);
}
}
我有一个 Angular 反应形式,人们 select 他们最喜欢的水果最少 1 种,最多 3 种。
模板:
<div>
<h3>Which maximum 3 fruits do you like best?</h3>
<form *ngIf="myForm" [formGroup]="myForm" (ngSubmit)="onSubmit(myForm.value)" novalidate>
<div *ngFor="let answer of answers.controls; let i=index">
<input type="checkbox" [formControl]="answer">{{fruits[i]}}<br>
</div>
<button type="submit" [disabled]="!myForm.valid">Submit</button>
</form>
</div>
组件:
export class AppComponent {
myForm: FormGroup;
fruits: Array<string> = ["apple", "pear", "kiwi", "banana", "grape", "strawberry", "grapefruit", "melon", "mango", "plum"];
constructor(private formBuilder: FormBuilder) { }
ngOnInit() {
this.myForm = this.formBuilder.group({}, {
validator: this.anotherValidator.bind(this)
});
let answersFormArray = this.fruits.map(fruit => { return this.formBuilder.control(false, [this.validateMaxCheckboxes.bind(this)]) });
this.myForm.setControl('answers', this.formBuilder.array(answersFormArray));
}
validateMaxCheckboxes(control: FormControl) {
return null;
};
anotherValidator(group: FormGroup) {
return null;
};
get answers(): FormArray {
return this.myForm.get('answers') as FormArray;
};
onSubmit(submit) {
console.log(submit.answers);
}
}
你最喜欢哪三种水果?然后会显示一个水果列表(复选框),用户可以 select。
我想要这种行为:
如果用户select什么都没有,提交按钮被禁用,至少需要select编辑1个水果。如果用户 select 吃了 1 或 2 个水果,则启用提交按钮。如果用户 select 是第 3 个水果(选中 3 个复选框),我想禁用所有未选中的水果,提交按钮保持启用状态。如果取消选中 3 个水果中的一个,则启用所有复选框。这样,用户可以从列表中 select 最少 1 个和最多 3 个水果。
我尝试了很多东西,在谷歌上搜索了很多,但我无法让它工作。
@ArunKumaresh 的答案也有效,但与我的原始代码相去甚远。但他为我指出了正确的方向,所以我可以想出这个解决方案:
模板:
<div>
<h3>Which maximum 3 fruits do you like best</h3>
<form *ngIf="myForm" [formGroup]="myForm" (ngSubmit)="onSubmit(myForm)" novalidate>
<div *ngFor="let answer of answers.controls; let i=index">
<input type="checkbox" [formControl]="answer" (change)="onChangeAnswer($event.target.checked)">{{fruits[i]}}<br>
</div>
<button type="submit" [disabled]="!myForm.valid">Submit</button>
</form>
</div>
组件:
export class AppComponent {
fruits: Array<string> = ["apple", "pear", "kiwi", "banana", "grape", "strawberry", "grapefruit", "melon", "mango", "plum"];
myForm: FormGroup;
numChecked: number = 0;
constructor(private formBuilder: FormBuilder) { }
ngOnInit() {
this.myForm = this.formBuilder.group({}, {
validator: this.minOneAnswer.bind(this)
});
let answersFormArray = this.fruits.map(fruit => { return this.formBuilder.control(false) });
this.myForm.setControl('answers', this.formBuilder.array(answersFormArray));
}
minOneAnswer(control) {
return this.numChecked === 0 ? { minOneAnswerChecked: true } : null;
}
onChangeAnswer(checked: boolean) {
checked ? this.numChecked++ : this.numChecked--;
const answerFormArray = this.myForm.get('answers') as FormArray;
if (this.numChecked >= 3) {
answerFormArray.controls.forEach((item) => {
if (!item.value) item.disable()
})
} else {
answerFormArray.controls.forEach((item) => {
if (!item.value) item.enable()
})
}
}
get answers(): FormArray {
return this.myForm.get('answers') as FormArray;
};
onSubmit(form: FormGroup) {
const answerFormArray = form.get('answers') as FormArray;
answerFormArray.controls.forEach((item) => {
if (!item.value) item.enable()
})
console.log(form.value);
}
}