【问题标题】:Checkbox Group handling and Validation in Angular2Angular2中的复选框组处理和验证
【发布时间】:2017-02-02 03:17:50
【问题描述】:

我不明白,应该如何在 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的初始值存在第三个问题,它只是一个空数组,但会导致最初检查所有复选框(如果初始值设置为string则不会发生),虽然我在 DOM 中找不到任何 checked 属性。

我正在使用最新的 ionic beta (2.0.0-beta.10),它使用 angular/core 版本 2.0.0-rc.4 和 angular/forms 版本 0.2.0。

那么,有没有关于如何使用复选框组的指南?有什么建议或想法吗?

【问题讨论】:

    标签: angular ionic-framework ionic2 angular2-forms


    【解决方案1】:

    如果您选中一个复选框,然后取消选中它,即使未选中,FormControl 仍会将其显示为有效。它可能只需要真值和假值。你可以试试这个代码示例,因为它对我有用 -

                                 mustBeChecked(control: FormControl): {[key: string]: string} {
                                  if (!control.value) {
                                  return {mustBeCheckedError: 'Must be checked'};
                                   } else {
                                           return null;
                                          }
                                    }
    

    你也可以参考这个plunker

    这里目前存在一个未解决的问题,点击事件在更改值之前触发。参考github链接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">
    

    【讨论】:

      【解决方案2】:

      第一个问题来自验证。如果选中和取消选中一个复选框(并且没有选中其他复选框),则输入仍然有效 - 有点奇怪。

      我注意到如果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 在语言可用之前不会被实例化,这主要是个人喜好,我相信您可以将languagesselectedLanguages 异步附加到您的modelForm,但它简化了同步构建它的事情。

      我取出translateService.get('languages') | async,我注意到在模板中调用此函数时出现了一些奇怪的行为,我更喜欢在组件中解开我的可观察对象,以捕获加载/错误状态。

      它不像某些原生复选框数组表单控件那样优雅,但它干净且非常灵活。查看the plunker,如果您有任何问题,请告诉我!

      【讨论】:

      • 我试过了,它奏效了,天哪,所以如果我们有多个复选框组,我们实际上是疯狂地使用响应式表单:/
      猜你喜欢
      • 2012-04-20
      • 2017-11-22
      • 1970-01-01
      • 2021-07-15
      • 2017-07-28
      • 1970-01-01
      • 1970-01-01
      • 2012-12-14
      • 2013-11-07
      相关资源
      最近更新 更多