Angular2 中的复选框组处理和验证
Checkbox Group handling and Validation in Angular2
我不明白,应该如何在 angular2 的模型驱动形式中处理复选框组。
模型有一个 属性 languages
,我这样实例化它:
this.model = {
languages: []
};
使用 FormBuilder
创建表单:
this.modelForm = this.formBuilder.group({
'languages': [model.languages, Validators.required],
});
和模板:
<div *ngFor="let language of translateService.get('languages') | async | key_value">
<input type="checkbox" name="languages[]" formControlName="languages" value="{{ language.key }}" id="language_{{ language.key }}">
<label attr.for="language_{{ language.key }}">{{ language.value }}</label>
</div>
需要 div
用于样式目的(自定义复选框),显然 key_value
使语言的键和值在循环中可用。
第一个问题是验证。如果选中和取消选中一个复选框(并且没有选中其他复选框),输入仍然有效 - 有点奇怪。
第二个问题与值有关,如果选中两种或更多语言,则为 true
,否则为 false
。
然后是 languages
的初始值的第三个问题,它只是一个空数组,但会导致所有复选框在初始时被选中(如果初始值设置为 [,则不会发生) =20=]),尽管我无法在 DOM.
中发现任何 checked
属性
我正在使用最新的 ionic beta (2.0.0-beta.10),它使用 angular/core 版本 2.0.0-rc.4 和 angular/forms 版本 0.2.0。
那么,是否有关于如何使用复选框组的指南?有什么建议或想法吗?
The first problem comes with validation. If one checks and unchecks a checkbox (and no other checkbox is checked), the input is still valid - somehow strange.
我注意到如果 languages
的值是空数组,它会通过 Validations.required
检查。
The second problem comes with the value, which is true if two ore more languages are checked and false otherwise.
Then there is a third problem with the initial value of languages which is just an empty array, but causes all checkboxes to be checked initially (doesn't happen if the initial value is set to a string), although I can not spot any checked attribute in the DOM.
我认为问题在于您将多个控件绑定到单个 FormControl
的方式,我认为需要涉及 FormArray
,可能需要使用不同的 FormControl
来存储复选框数组的结果。
So, is there any guide on how to work with checkbox groups? Any advice or ideas?
当然,我试了一下实现它,我会先 post 实现,然后是一些注释。您可以在 https://plnkr.co/edit/hFU904?p=preview
查看实际效果
@Component({
template: `
<template [ngIf]="loading">
Loading languages...
</template>
<template [ngIf]="!loading">
<form [formGroup]="modelForm">
<div [formArrayName]="'languages'" [class.invalid]="!modelForm.controls.selectedLanguages.valid">
<div *ngFor="let language of modelForm.controls.languages.controls; let i = index;" [formGroup]="language">
<input type="checkbox" formControlName="checked" id="language_{{ language.controls.key.value }}">
<label attr.for="language_{{ language.controls.key.value }}">{{ language.controls.value.value }}</label>
</div>
</div>
<hr>
<pre>{{modelForm.controls.selectedLanguages.value | json}}</pre>
</form>
</template>
`
})
export class AppComponent {
loading:boolean = true;
modelForm:FormGroup;
languages:LanguageKeyValues[];
constructor(public formBuilder:FormBuilder){
}
ngOnInit() {
this.translateService.get('languages').subscribe((languages:LanguageKeyValues[]) => {
let languagesControlArray = new FormArray(languages.map((l) => {
return new FormGroup({
key: new FormControl(l.key),
value: new FormControl(l.value),
checked: new FormControl(false),
});
}));
this.modelForm = new FormGroup({
languages: languagesControlArray,
selectedLanguages: new FormControl(this.mapLanguages(languagesControlArray.value), Validators.required)
});
languagesControlArray.valueChanges.subscribe((v) => {
this.modelForm.controls.selectedLanguages.setValue(this.mapLanguages(v));
});
this.loading = false;
});
}
mapLanguages(languages) {
let selectedLanguages = languages.filter((l) => l.checked).map((l) => l.key);
return selectedLanguages.length ? selectedLanguages : null;
}
}
这里的主要区别是我将您的 model.languages
合并到您的 modelForm
中,现在在模板中重复 modelForm.languages
FormArray
。
modelForm.languages
已变为 modelForm.selectedLanguages
,现在是基于 modelForm.languages
中检查值的计算值。如果未选择任何内容,modelForm.selectedLanguages
将设置为空,以失败验证。
modelForm
在语言可用之前不会实例化,这主要是个人喜好,我相信您可以将 languages
和 selectedLanguages
异步附加到您的 modelForm
, 但它简化了同步构建它的事情。
我取出 translateService.get('languages') | async
,我注意到在模板中调用此函数时有一些奇怪的行为,我更喜欢在组件中解包我的 observables,以捕获 loading/error 状态。
它不像某些本机复选框数组表单控件那样优雅,但它干净且非常灵活。查看 the plunker 如果您有任何问题,请告诉我!
如果您选中一个复选框然后取消选中它,FormControl 仍然会显示它有效,即使它没有被选中。可能只需要 true 和 false values.You 就可以尝试这个代码示例,因为它对我有用 -
mustBeChecked(control: FormControl): {[key: string]: string} {
if (!control.value) {
return {mustBeCheckedError: 'Must be checked'};
} else {
return null;
}
}
你也可以参考这个plunker
目前这里有一个悬而未决的问题,即在更改值之前触发点击事件。参考github link here。希望对你有帮助。
多个复选框有不同的解决方法,例如使用
event.target.checked
而不是模型中的值。
您可以像在本示例中那样使用它 -
<input type="checkbox"
(change)="expression && expression.Option1=$event.target.checked ? true : undefiend"
[ngModel]="expression?.Option1">
<input type="checkbox"
(change)="expression && expression.Option2=$event.target.checked ? true : undefiend"
[ngModel]="expression?.Option2">
我不明白,应该如何在 angular2 的模型驱动形式中处理复选框组。
模型有一个 属性 languages
,我这样实例化它:
this.model = {
languages: []
};
使用 FormBuilder
创建表单:
this.modelForm = this.formBuilder.group({
'languages': [model.languages, Validators.required],
});
和模板:
<div *ngFor="let language of translateService.get('languages') | async | key_value">
<input type="checkbox" name="languages[]" formControlName="languages" value="{{ language.key }}" id="language_{{ language.key }}">
<label attr.for="language_{{ language.key }}">{{ language.value }}</label>
</div>
需要 div
用于样式目的(自定义复选框),显然 key_value
使语言的键和值在循环中可用。
第一个问题是验证。如果选中和取消选中一个复选框(并且没有选中其他复选框),输入仍然有效 - 有点奇怪。
第二个问题与值有关,如果选中两种或更多语言,则为 true
,否则为 false
。
然后是 languages
的初始值的第三个问题,它只是一个空数组,但会导致所有复选框在初始时被选中(如果初始值设置为 [,则不会发生) =20=]),尽管我无法在 DOM.
checked
属性
我正在使用最新的 ionic beta (2.0.0-beta.10),它使用 angular/core 版本 2.0.0-rc.4 和 angular/forms 版本 0.2.0。
那么,是否有关于如何使用复选框组的指南?有什么建议或想法吗?
The first problem comes with validation. If one checks and unchecks a checkbox (and no other checkbox is checked), the input is still valid - somehow strange.
我注意到如果 languages
的值是空数组,它会通过 Validations.required
检查。
The second problem comes with the value, which is true if two ore more languages are checked and false otherwise.
Then there is a third problem with the initial value of languages which is just an empty array, but causes all checkboxes to be checked initially (doesn't happen if the initial value is set to a string), although I can not spot any checked attribute in the DOM.
我认为问题在于您将多个控件绑定到单个 FormControl
的方式,我认为需要涉及 FormArray
,可能需要使用不同的 FormControl
来存储复选框数组的结果。
So, is there any guide on how to work with checkbox groups? Any advice or ideas?
当然,我试了一下实现它,我会先 post 实现,然后是一些注释。您可以在 https://plnkr.co/edit/hFU904?p=preview
查看实际效果@Component({
template: `
<template [ngIf]="loading">
Loading languages...
</template>
<template [ngIf]="!loading">
<form [formGroup]="modelForm">
<div [formArrayName]="'languages'" [class.invalid]="!modelForm.controls.selectedLanguages.valid">
<div *ngFor="let language of modelForm.controls.languages.controls; let i = index;" [formGroup]="language">
<input type="checkbox" formControlName="checked" id="language_{{ language.controls.key.value }}">
<label attr.for="language_{{ language.controls.key.value }}">{{ language.controls.value.value }}</label>
</div>
</div>
<hr>
<pre>{{modelForm.controls.selectedLanguages.value | json}}</pre>
</form>
</template>
`
})
export class AppComponent {
loading:boolean = true;
modelForm:FormGroup;
languages:LanguageKeyValues[];
constructor(public formBuilder:FormBuilder){
}
ngOnInit() {
this.translateService.get('languages').subscribe((languages:LanguageKeyValues[]) => {
let languagesControlArray = new FormArray(languages.map((l) => {
return new FormGroup({
key: new FormControl(l.key),
value: new FormControl(l.value),
checked: new FormControl(false),
});
}));
this.modelForm = new FormGroup({
languages: languagesControlArray,
selectedLanguages: new FormControl(this.mapLanguages(languagesControlArray.value), Validators.required)
});
languagesControlArray.valueChanges.subscribe((v) => {
this.modelForm.controls.selectedLanguages.setValue(this.mapLanguages(v));
});
this.loading = false;
});
}
mapLanguages(languages) {
let selectedLanguages = languages.filter((l) => l.checked).map((l) => l.key);
return selectedLanguages.length ? selectedLanguages : null;
}
}
这里的主要区别是我将您的 model.languages
合并到您的 modelForm
中,现在在模板中重复 modelForm.languages
FormArray
。
modelForm.languages
已变为 modelForm.selectedLanguages
,现在是基于 modelForm.languages
中检查值的计算值。如果未选择任何内容,modelForm.selectedLanguages
将设置为空,以失败验证。
modelForm
在语言可用之前不会实例化,这主要是个人喜好,我相信您可以将 languages
和 selectedLanguages
异步附加到您的 modelForm
, 但它简化了同步构建它的事情。
我取出 translateService.get('languages') | async
,我注意到在模板中调用此函数时有一些奇怪的行为,我更喜欢在组件中解包我的 observables,以捕获 loading/error 状态。
它不像某些本机复选框数组表单控件那样优雅,但它干净且非常灵活。查看 the plunker 如果您有任何问题,请告诉我!
如果您选中一个复选框然后取消选中它,FormControl 仍然会显示它有效,即使它没有被选中。可能只需要 true 和 false values.You 就可以尝试这个代码示例,因为它对我有用 -
mustBeChecked(control: FormControl): {[key: string]: string} {
if (!control.value) {
return {mustBeCheckedError: 'Must be checked'};
} else {
return null;
}
}
你也可以参考这个plunker
目前这里有一个悬而未决的问题,即在更改值之前触发点击事件。参考github link here。希望对你有帮助。
多个复选框有不同的解决方法,例如使用
event.target.checked
而不是模型中的值。
您可以像在本示例中那样使用它 -
<input type="checkbox"
(change)="expression && expression.Option1=$event.target.checked ? true : undefiend"
[ngModel]="expression?.Option1">
<input type="checkbox"
(change)="expression && expression.Option2=$event.target.checked ? true : undefiend"
[ngModel]="expression?.Option2">