【问题标题】:Requiring a checkbox to be checked需要选中一个复选框
【发布时间】:2016-05-29 11:43:39
【问题描述】:

我希望在使用 Angular 的 FormBuilder 选中复选框之前禁用按钮。我不想明确检查复选框的值,而是更喜欢使用验证器,以便我可以简单地检查form.valid

在下面的两种验证情况下,复选框都是

interface ValidationResult {
  [key:string]:boolean;
}

export class CheckboxValidator {
  static checked(control:Control) {
    return { "checked": control.value };
  }
}

@Component({
  selector: 'my-form',
  directives: [FORM_DIRECTIVES],
  template: `  <form [ngFormModel]="form" (ngSubmit)="onSubmit(form.value)">
    <input type="checkbox" id="cb" ngControl="cb">
    <button type="submit" [disabled]="!form.valid">
    </form>`
})

export class SomeForm {
  regForm: ControlGroup;

  constructor(fb: FormBuilder) {
    this.form = fb.group({
      cb: [ CheckboxValidator.checked ]
      //cb: [ false, Validators.required ] <-- I have also tried this
    });
  }

  onSubmit(value: any) {
    console.log('Submitted: ', this.form);
  }
}

【问题讨论】:

  • 那么有什么问题,你的第二个版本工作正常[ false, Validators.required ]
  • 在第二种情况下,至少对我来说,this.form.value{ cb: false }this.form.validtrue
  • 看答案。 this.form.valid 已不复存在true.
  • 现在可以使用Validators.requiredTrue

标签: angular angular2-forms angular-reactive-forms


【解决方案1】:

.ts

@Component({
  selector: 'my-app', 
  template: `
    <h1>LOGIN</h1>
    <form [ngFormModel]="loginForm"  #fm="ngForm"  (submit)="doLogin($event)"> 

          <input type="checkbox" id="cb" ngControl="cb" #cb="ngForm" required>
          <button type="submit" [disabled]="!loginForm.valid">Log in</button>

          <br/>
              <div>Valid ={{cb.valid}}</div>
              <div>Pristine ={{cb.pristine}}</div>
              <div>Touch ={{cb.touched}}</div>
              <div>form.valid?={{loginForm.valid}}</div>
          <BR/>
          <BR/>

    </form>
    `,
  directives: [ROUTER_DIRECTIVES,FORM_DIRECTIVES,CORE_DIRECTIVES]
})

export class Login { 
  constructor(fb: FormBuilder) {
    this.loginForm = fb.group({
      cb: [false, Validators.required],
    //cb: ['',Validators.required] - this will also work.

    });
  }
  doLogin(event) {
    console.log(this.loginForm);
    event.preventDefault();
  }
}

Working Plunker

如果需要任何更改,请告诉我。

【讨论】:

  • 所以两件事。首先,您在 HTML 中有 required,这正是我试图避免的。但是为您的 plnkr 删除它仍然可以按预期工作。但是,plnkr 使用的是 beta.0。如果您删除 HTML 中的 required 并移至 beta.6,这将不再有效。这可能是 Angular 的一个错误。
  • 因此,在 angular github repo 中进行了一些挖掘之后,正确的解决方法是不要将复选框值设置为 false,而是设置为 ''。所以对于 beta.6,正确的方法是cb: ['', Validators.required]。如果您编辑答案,我会将其标记为正确。
  • 当我在没有任何编辑的情况下发布我的答案时,我将其与' ' 放在了一起。但是您可以检查一下,这也可以正常工作,没有任何问题。您可以将其标记为已回答。我会用// cb:[' ',Validators.required] 更新它。因此其他用户将能够看到使用validator.required 的其他方式。
  • 您需要使用Validators.requiredTrue 才能使其正常工作。否则,如果您选中并取消选中,它仍然是“有效的”。
【解决方案2】:

我发现 Validator.required 不适用于复选框。 如果您选中一个复选框,然后取消选中它,即使未选中,FormControl 仍会将其显示为有效。我认为它只会检查您是否将其设置为真或假。

这是一个快速简单的验证器,您可以将其添加到您的 FormControl:

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

【讨论】:

  • 你可以用Validators.requiredTrue代替Validators.required
【解决方案3】:

您可以只使用 ValidatorPattern 并检查正确的(布尔值)值:

<input type="checkbox" [formControl]="myForm.controls['isTosRead']">

这里是绑定:

this.myForm = builder.group({
        isTosRead: [false, Validators.pattern('true')]
    });

【讨论】:

  • 这是最好的答案恕我直言。也可以使用formControlName="isTosRead" 而不是[formControl]="..."
  • 这太棒了!在 Angular 4 中对我来说效果很好
【解决方案4】:

我有一个非常简单的例子:

在您的组件中:

login : FormGroup;

constructor(@Inject(FormBuilder)formBuilder : FormBuilder) {
this.login = formBuilder.group({userName: [null], password: [null],
staySignedIn: [false,Validators.pattern('true')]});
}

在您的 HTML 中:

<form [formGroup]="login" (ngSubmit)="onSubmit()">
    <div class="form-group">
        <input formControlName="userName" required>
    </div>
    <div class="form-group">
        <input formControlName="password" type="password" required>
    </div>
    <div>
        <label>
    <input formControlName="staySignedIn" checked="staySignedIn" type="checkbox"> bla
  </label>
    </div>
    <button type="submit">bla</button>
    <div >
        <a href>bla?</a>
    </div>
</form>

【讨论】:

    【解决方案5】:

    由于Angular 2.3.1,您可以使用Validators#requiredTrue

    组件:

    this.formGroup = this.formBuilder.group({
      cb: [false, Validators.requiredTrue]
    });
    

    模板:

    <form [formGroup]="formGroup">
      <label><input type="checkbox" formControlName="cb"> Accept it</label>
      <div style="color: red; padding-top: 0.2rem" *ngIf="formGroup.hasError('required', 'cb')">
        Required
      </div>
      <hr>
      <div>
        <button type="submit" [disabled]="formGroup.invalid">Submit</button>
      </div>
    </form>
    

    STACKBLITZ DEMO

    【讨论】:

    • Validators.requiredTrue 是关键!
    • Validators.requiredTrue 不适用于 Angular 5
    • @ryanrain 请说明为什么它不适合你。
    • 我正在使用 Angular CLI: 7.3.8Validators.requiredTrue 非常适合我。谢谢@developer033
    • 如果您有 2 个复选框并使用 Validators.requiredTrue ,则需要所有复选框到 true,我的要求需要至少一个复选框为 true(如果您有多个复选框),有人对如何解决这个问题有建议吗? stackoverflow.com/questions/57895884/…
    【解决方案6】:
    <h1>LOGIN</h1>
    <form [formGroup]="signUpForm"> 
        <input type="checkbox" formControlName="cb">
        <button type="submit" [disabled]="!loginForm.valid" (click)="doLogin()">Log in</button>
    </form>
    
    export class Login { 
      public signUpForm: FormGroup;
    
      constructor(fb: FormBuilder) {
        this.signUpForm = fb.group({
          cb: [false, Validators.requiredTrue]
        });
      }
      doLogin() {
    
      }
    }
    

    【讨论】:

      【解决方案7】:

      对于 Angular 8,我像下面这样检查三个复选框中是否至少有一个复选框被选中

      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...
        });
      

      创建了一个自定义验证器

      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;
        };
      }
      

      并在 html 中像下面这样使用它

      <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>
      

      【讨论】:

        【解决方案8】:

        创建一个检测任何变化的方法

        checkValue(event: any) {
            this.formulario.patchValue({
              checkboxControlName: event.target.checked
            })
        }
        

        将该方法放在事件更改和ngModel required 属性上

        <input (change)="checkValue($event)" type="checkbox" formControlName="checkboxControlName" value="true" ngModel required>
        

        并使用传统方式进行验证

        this.formulario = new FormGroup({
          checkboxControlName: new FormControl('', [Validators.required])
        });
        

        Source

        【讨论】:

          【解决方案9】:

          如果您使用 PrimeNG,您可以通过 TAG app-form-required-field 来完成,如下所示:

          <p-checkbox name="_yes" #active="ngModel" required value="true" 
          label="Active" binary="true" [(ngModel)]="filter._yes"></p-checkbox>
          
          <p-checkbox name="_no" #inactive="ngModel" required label="Inactive" 
          binary="true" [(ngModel)]="filter._no"></p-checkbox>
          
          <app-form-required-field
               *ngIf="!filter._yes && !filter._no"
               [form]="active"
               [form]="inactive"
               id="msgAtivo"
               requiredMessage="Field required!"
          >
          </app-form-required-field>
          

          【讨论】:

            【解决方案10】:

            HTML 表单

            <div class="col-md-12">
                              <div class="form-group">
                                  <input type="checkbox" class="form-check-input" id="agree" formControlName="agree">
                                  <label class="form-check-label" for="agree">
                                    I agree to our <a target="_blank" href="#">Terms of use</a> and
                                    <a target="_blank" href="#">Privacy Policy</a>.
                                  </label>
                                  <div class="text-danger" *ngIf="(isRegSubmit||regForm.get('agree').touched) &&
                                      regForm.get('agree').hasError('required')">
                                      Please agree to terms of use and privacy policy.
                                  </div>
                              </div>
                          </div>
            

            TS 文件

              regForm: FormGroup;isRegSubmit: boolean = false;
              constructor(
                private fb: FormBuilder
              }
            
              this.regForm = this.fb.group({
                    agree    : [false, Validators.requiredTrue]
                });
            

            Validators.required 无效 此外,我们也可以通过检查值来显示错误消息并限制用户提交,但这不是一个好方法,因为我们没有使用验证,所以只要只有一个复选框,然后添加 Validators.requiredTrue 而不是 Validators。必填

            【讨论】:

              【解决方案11】:

              尽管将验证器简单检查置于条件之下

              @Component({
                selector: 'my-form',
                directives: [FORM_DIRECTIVES],
                template: `  <form [ngFormModel]="form" (ngSubmit)="onSubmit(form.value)">
                  <input type="checkbox" id="cb" ngControl="cb">
                  <button type="submit" [disabled]="!form.valid && !cb.value">
                  </form>`
              })
              

              【讨论】:

                【解决方案12】:

                成分:

                import { FormGroup, FormBuilder, Validators, AbstractControl } from '@angular/forms';
                
                public profileForm!: FormGroup;
                
                constructor(
                    private _fb: FormBuilder
                  ) { }
                  
                ngOnInit(): void {
                    this._createForm();
                    this._setValidationRule();
                }
                
                get fc(): { [key: string]: AbstractControl } {
                    return this.profileForm.controls;
                  }
                
                  private _createForm() {
                    const self = this;
                    self.profileForm = self._fb.group({
                      required_checkbox: [false],
                      zipcode: [''],
                      city: [''],
                      town: [''],
                    });
                  }
                  
                  private _setValidationRule() {
                    const self = this;
                    self.profileForm.get('required_checkbox').valueChanges.subscribe(
                      ruleStatus => {
                        if (ruleStatus) {
                          self.profileForm.get('zipcode').setValidators(Validators.required);
                          self.profileForm.get('city').setValidators(Validators.required);
                          self.profileForm.get('town').setValidators(Validators.required);
                        } else {
                          self.profileForm.get('zipcode').setValidators(null);
                          self.profileForm.get('city').setValidators(null);
                          self.profileForm.get('town').setValidators(null);
                        }
                        self.profileForm.get('zipcode').updateValueAndValidity();
                        self.profileForm.get('city').updateValueAndValidity();
                        self.profileForm.get('town').updateValueAndValidity();
                      });
                  }
                

                模板

                <mat-checkbox class="terms" formControlName="required_checkbox">Pickup Riraku</mat-checkbox>
                        
                <mat-form-field appearance="outline">
                    <mat-label>Zip Code</mat-label>
                    <input matInput type="text" formControlName="zipcode" placeholder="">
                </mat-form-field>
                
                <mat-form-field appearance="outline">
                    <mat-label>City</mat-label>
                    <input matInput type="text" formControlName="city" placeholder="">
                </mat-form-field>
                
                <mat-form-field appearance="outline">
                    <mat-label>Town</mat-label>
                    <input matInput type="text" formControlName="town" placeholder="">
                </mat-form-field>
                

                【讨论】:

                  【解决方案13】:

                  要在复选框中设置值,复选框本身可以有值,也可以没有值。因此,您可以在Validators.required 上进行测试,并在选中时传递值或 true,如果未选中则传递 null 或 false。 并触发 onChangeInput 方法:

                  public changeInput(event): void {
                    this.isChecked = event.target.checked;
                    // passing the value
                    this.onChange(this.isChecked ? (this.value ? this.value : true) : false);
                    // set touched
                    if (!this.isTouched) {
                      this.isTouched = true;
                      this.onTouch();
                    }
                  }

                  【讨论】:

                    猜你喜欢
                    • 2012-05-31
                    • 1970-01-01
                    • 1970-01-01
                    • 2019-10-17
                    • 2012-04-04
                    • 2015-01-14
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多