第一个问题来自验证。如果选中和取消选中一个复选框(并且没有选中其他复选框),则输入仍然有效 - 有点奇怪。
我注意到如果languages 的值是一个空数组,它通过Validations.required 检查。
第二个问题与值有关,如果检查两种或多种语言,则为 true,否则为 false。
然后语言的初始值存在第三个问题,它只是一个空数组,但会导致最初检查所有复选框(如果初始值设置为字符串则不会发生),尽管我不能在 DOM 中发现任何选中的属性。
我认为问题在于您将多个控件绑定到单个FormControl 的方式,我认为需要涉及FormArray,可能使用不同的FormControl 存储您的复选框数组的结果。
那么,有没有关于如何使用复选框组的指南?有什么建议或想法吗?
当然,我尝试了实现它,我将首先发布实现,然后是一些注释。你可以在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 将设置为 null,验证失败。
modelForm 在语言可用之前不会被实例化,这主要是个人喜好,我相信您可以将languages 和selectedLanguages 异步附加到您的modelForm,但它简化了同步构建它的事情。
我取出translateService.get('languages') | async,我注意到在模板中调用此函数时出现了一些奇怪的行为,我更喜欢在组件中解开我的可观察对象,以捕获加载/错误状态。
它不像某些原生复选框数组表单控件那样优雅,但它干净且非常灵活。查看the plunker,如果您有任何问题,请告诉我!