我想在没有表单标签的情况下对复选框进行验证。 至少应选择一个复选框。
<div *ngFor="let item of officeLIST">
<div *ngIf=" item.officeID == 1">
<input #off type="checkbox" id="off" name="off" value="1" [(ngModel)]="item.checked">
<label>{{item.officename}}</label>
</div>
<div *ngIf="item.officeID== 2">
<input #off type="checkbox" id="off" name="off" value="2" [(ngModel)]="item.checked">
<label>{{item.officename}}</label>
</div>
<div *ngIf="item.officeID== 3">
<input #off type="checkbox" id="off" name="off" value="3" [(ngModel)]="item.checked">
<label>{{item.officename}}</label>
</div>
</div>
对于其他字段我将把所需要的并执行错误|触摸|有效等但由于复选框不是单输入,我不能在每个复选框中放置所需,因为所有复选框都必须被选中。那么如何进行验证以提醒用户至少应检查一个?
答案 0 :(得分:19)
考虑创建一个包含您的复选框组的FormGroup
,并将组的已检查值绑定到带有必需验证程序的隐藏表单控件。
假设您有三个复选框
items = [
{key: 'item1', text: 'value1'}, // checkbox1 (label: value1)
{key: 'item2', text: 'value2'}, // checkbox2 (label: value2)
{key: 'item3', text: 'value3'}, // checkbox3 (label: value3)
];
第1步:为您的复选框定义FormArray
let checkboxGroup = new FormArray(this.items.map(item => new FormGroup({
id: new FormControl(item.key), // id of checkbox(only use its value and won't show in html)
text: new FormControl(item.text), // text of checkbox(show its value as checkbox's label)
checkbox: new FormControl(false) // checkbox itself
})));
*易于通过 ngFor
显示
第2步:创建隐藏的必需formControl以保持复选框组的状态
let hiddenControl = new FormControl(this.mapItems(checkboxGroup.value), Validators.required);
// update checkbox group's value to hidden formcontrol
checkboxGroup.valueChanges.subscribe((v) => {
hiddenControl.setValue(this.mapItems(v));
});
我们只关心隐藏控件所需的验证状态,并且不会在html中显示此隐藏控件。
Step3:创建最终表单组包含下面的复选框组和隐藏的formControl
this.form = new FormGroup({
items: checkboxGroup,
selectedItems: hiddenControl
});
Html模板:
<form [formGroup]="form">
<div [formArrayName]="'items'" [class.invalid]="!form.controls.selectedItems.valid">
<div *ngFor="let control of form.controls.items.controls; let i = index;" [formGroup]="control">
<input type="checkbox" formControlName="checkbox" id="{{ control.controls.id.value }}">
<label attr.for="{{ control.controls.id.value }}">{{ control.controls.text.value }}</label>
</div>
</div>
<div [class.invalid]="!form.controls.selectedItems.valid" *ngIf="!form.controls.selectedItems.valid">
checkbox group is required!
</div>
<hr>
<pre>{{form.controls.selectedItems.value | json}}</pre>
</form>
参考此demo。
答案 1 :(得分:13)
使用reactive forms的最佳,最简单且可能正确的方法是使用一个FormGroup来保存分组的复选框,并创建一个验证器以检查其中是否至少选中了一个(或多个)复选框。组。
要这样做,只需在现有FormGroup
内创建另一个FormGroup
并在其上附加一个验证器:
form = new FormGroup({
// ...more form controls...
myCheckboxGroup: new FormGroup({
myCheckbox1: new FormControl(false),
myCheckbox2: new FormControl(false),
myCheckbox3: new FormControl(false),
}, requireCheckboxesToBeCheckedValidator()),
// ...more form controls...
});
这是验证器。我做到了,所以您甚至可以使用它来检查是否至少选中了X复选框,例如requireCheckboxesToBeCheckedValidator(2)
:
import { FormGroup, ValidatorFn } from '@angular/forms';
export function requireCheckboxesToBeCheckedValidator(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 {
requireCheckboxesToBeChecked: true,
};
}
return null;
};
}
不要忘记在模板中添加指令“ formGroupName”来包装您的复选框。但是不用担心,如果您忘记了,编译器会通过错误消息提醒您。然后,您可以像在FormControl上一样检查复选框组是否有效:
<ng-container [formGroup]="form">
<!-- ...more form controls... -->
<div class="form-group" formGroupName="myCheckboxGroup">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" formControlName="myCheckbox1" id="myCheckbox1">
<label class="custom-control-label" for="myCheckbox1">Check</label>
</div>
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" formControlName="myCheckbox2" id="myCheckbox2">
<label class="custom-control-label" for="myCheckbox2">At least</label>
</div>
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" formControlName="myCheckbox3" id="myCheckbox3">
<label class="custom-control-label" for="myCheckbox3">One</label>
</div>
<div class="invalid-feedback" *ngIf="form.controls['myCheckboxGroup'].errors && form.controls['myCheckboxGroup'].errors.requireCheckboxesToBeChecked">At least one checkbox is required to check</div>
</div>
<!-- ...more form controls... -->
</ng-container>
*此模板非常静态。当然,您可以使用包含表单数据(FormControl的键,标签,必需等)的附加数组来动态创建它,并使用 ngFor
我创建了一个工作示例,您可以使用它:https://stackblitz.com/edit/angular-at-least-one-checkbox-checked
答案 2 :(得分:2)
在验证(例如某些点击事件)上迭代您的数组并检查至少有一个项是否为真。
let isSelected: any = this.officeLIST.filter((item) => item.checked === true);
if(isSelected != null && isSelected.length > 0) {
//At least one is selected
}else {
alert("select at least one");
}
答案 3 :(得分:2)
我遇到了同样的问题,这是我最终与Angular 6 FormGroup一起使用的解决方案,因为我没有几个复选框。
HTML 注意:我正在使用Angular Material进行样式设置,请根据需要进行更改。
<form [formGroup]="form">
<mat-checkbox formControlName="checkbox1">First Checkbox</mat-checkbox>
<mat-checkbox formControlName="checkbox2">Second Checkbox</mat-checkbox>
<mat-checkbox formControlName="checkbox3">Third Checkbox</mat-checkbox>
</form>
TypeScript
form: FormGroup;
constructor(private formBuilder: FormBuilder){}
ngOnInit(){
this.form = this.formBuilder.group({
checkbox1: [''],
checkbox2: [''],
checkbox3: [''],
});
this.form.setErrors({required: true});
this.form.valueChanges.subscribe((newValue) => {
if (newValue.checkbox1 === true || newValue.checkbox2 === true || newValue.checkbox3 === true) {
this.form.setErrors(null);
} else {
this.form.setErrors({required: true});
}
});
}
基本上,订阅表单中的所有更改,然后根据新的表单值根据需要修改错误。
答案 4 :(得分:0)
将(ngModelChange)=“ onChange(officeLIST)”添加到您的复选框,并在.ts文件中包含以下代码。
onChange(items) {
var found = items.find(function (x) { return x.checked === true; });
if (found)
this.isChecked = true;
else
this.isChecked = false;
}
在任何需要的地方使用isChecked变量。
答案 5 :(得分:-1)
您应该检查表单元素的触及和脏条件
int get_position()
{
CFArrayRef a = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
NSArray * arr = CFBridgingRelease(a);
pid_t window_pid = 0;
unsigned long count = [ arr count];
NSMutableDictionary* entry;
for ( unsigned long i = 0; i < count; i++)
{
//CFTypeRef position;
AXValueRef temp;
CGPoint current_point;
entry = arr[i];
window_pid = [[entry objectForKey:(id)kCGWindowOwnerPID] intValue];
NSString * temp_ns_string = [entry objectForKey:(id)kCGWindowName ];
const char *window_name =[temp_ns_string UTF8String];
printf("%s - ", window_name);
printf("Pid: %i\n", window_pid);
AXUIElementRef window_ref = AXUIElementCreateApplication(window_pid);
AXError error = AXUIElementCopyAttributeValue(window_ref, kAXPositionAttribute, (CFTypeRef *)&temp);
if ((AXValueGetValue(temp, kAXValueCGPointType, ¤t_point) ))
{
printf("%s - ", window_name);
printf("Pid: %i - ", window_pid);
printf(" %f,%f\n", current_point.x, current_point.y);
}
else
{
printf("%s - ", window_name);
printf("Pid: %i\n", window_pid);
}
}
return 0;
}
您可以将两个场景的前一个和我的答案结合起来