【问题标题】:Angular custom Validator checkboxAngular 自定义验证器复选框
【发布时间】:2019-01-08 14:53:31
【问题描述】:

我正在 Angular 中制作自定义验证器。验证器的目的是在选中复选框时使某些字段成为必填字段。目前,它验证的输入始终是必需的,而不仅仅是在选中复选框时。 这是我的验证器代码:

import { FormControl, AbstractControl } from "../../../node_modules/@angular/forms";

   export function validateCheckbox(control:AbstractControl){
    const val = control.value;
    const check = control.root.get('checkbox'); //i think the problem is here: if i do .value i get an error

    if (check) {
        if (val === null || val === undefined || val === '') {
            return {
                validate: {
                  valid: false
                }
              };
        }else{
            return null;
        }
    }else{
        return null;
    }
}

我的组件使用验证器:

import { Component, OnInit, ViewEncapsulation } from '@angular/core';
import { FormGroup, FormBuilder, Validators, FormControl } from '@angular/forms';
import { Customer } from '../account/models/customer.model';
import { validateCheckbox } from './customValidators';


@Component({
  selector: 'caredeal-registration',
  templateUrl: './registration.component.html',
  styleUrls: ['./registration.component.scss'],
  encapsulation: ViewEncapsulation.None
})

export class RegistrationComponent implements OnInit {
  registerForm: FormGroup;

  constructor(private formBuilder: FormBuilder) {
    this.registerForm = this.formBuilder.group({
      name:['',[Validators.required,Validators.minLength(2)]],
      firstName:['',[Validators.required,Validators.minLength(2)]],
      email:['', [Validators.required,Validators.minLength(2)]],
      telephone:['',[Validators.required,Validators.minLength(9)]],
      mobilePhone:['',Validators.minLength(10)],
      type:[''],
      checkbox:[false],
      companyName:['',Validators.minLength(2)],
      rizivNumber:[''],
      taxNumber:['',Validators.minLength(2)],
      streetName:['', Validators.required],
      houseNumber:['',validateCheckbox],
      bus:[''],
      zipCode:['',[Validators.required,Validators.minLength(4)]],
      place:['',[Validators.required,Validators.minLength(2)]]
    })
   }

  ngOnInit() {
  }

}

我的html代码,复选框在代码末尾,验证器用于门牌输入。

<form [formGroup]="registerForm" (ngSubmit)="onFormSubmit()">
        <div class="container-fluid">
            <h3>Account informatie</h3>
            <div class="row">
                <div class="col-md-6">
                    <div class="input-group">
                        <span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
                        <input type="text" class="form-control" formControlName="name" placeholder="Naam">
                    </div>
                    <div class="input-group">
                        <span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
                        <input type="text" class="form-control" formControlName="firstName" placeholder="Voornaam">
                    </div>
                    <div class="input-group">
                        <span class="input-group-addon"><i class="glyphicon glyphicon-envelope"></i></span>
                        <input type="email" class="form-control" formControlName="email" placeholder="Email">
                    </div>
                </div>
                <div class="col-md-6">
                    <div class="input-group">
                        <span class="input-group-addon"><i class="glyphicon glyphicon-earphone"></i></span>
                        <input type="tel" class="form-control" formControlName="telephone" placeholder="Telefoon">
                    </div>
                    <div class="input-group">
                        <span class="input-group-addon"><i class="glyphicon glyphicon-earphone"></i></span>
                        <input type="tel" class="form-control" formControlName="mobilePhone" placeholder="GSM">
                    </div>
                    <div class="input-group">
                        <label for="sel1">Type klant:</label>
                        <select class="form-control" formControlName="type">
                            <option>1</option>
                            <option>2</option>
                            <option>3</option>
                            <option>4</option>
                        </select>
                    </div>
                </div>
            </div>
        </div>
        <div class="container-fluid">
            <h3>Bedrijfsgegevens</h3>
            <div class="row">
                <div class="col-xs-12">
                    <div class="input-group">
                        <span class="input-group-addon"><i class="glyphicon glyphicon-home"></i></span>
                        <input type="text" class="form-control" formControlName="companyName" placeholder="Bedrijfsnaam">
                    </div>
                    <div class="input-group">
                        <span class="input-group-addon"><i class="glyphicon glyphicon-home"></i></span>
                        <input type="number" class="form-control"formControlName="rizivNumber" placeholder="RIZIV-nummer">
                    </div>
                    <div class="input-group">
                        <span class="input-group-addon"><i class="glyphicon glyphicon-home"></i></span>
                        <input type="text" class="form-control" formControlName="taxNumber" placeholder="BTW-nummer">
                    </div>
                </div>
            </div>
        </div>
        <div class="container-fluid">
            <h3>Afleveradres</h3>
            <div class="row">
                <div class="col-xs-12">
                    <div class="input-group">
                        <span class="input-group-addon"><i class="glyphicon glyphicon-road"></i></span>
                        <input type="text" class="form-control" formControlName="streetName" placeholder="Straatnaam">
                    </div>
                    <div class="input-group">
                        <span class="input-group-addon"><i class="glyphicon glyphicon-sound-5-1"></i></span>
                        <input type="number" class="form-control" formControlName="houseNumber" placeholder="Huisnummer">
                    </div>
                    <div class="input-group">
                        <span class="input-group-addon"><i class="glyphicon glyphicon-inbox"></i></span>
                        <input type="text" class="form-control" formControlName="bus" placeholder="Bus">
                    </div>
                    <div class="input-group">
                        <span class="input-group-addon"><i class="glyphicon glyphicon-inbox"></i></span>
                        <input type="number" class="form-control" formControlName="zipCode" placeholder="Postcode">
                    </div>
                    <div class="input-group">
                        <span class="input-group-addon"><i class="glyphicon glyphicon-inbox"></i></span>
                        <input type="text" class="form-control" formControlName="place" placeholder="Plaats">
                    </div>
                    <div class="input-group">
                        <input type="checkbox" formControlName="checkbox"  name="">Facturatie adres is verschillend van afleveradres<br>
                    </div>
                    <div class="input-group">
                        <button type="submit" [disabled] = "!registerForm.valid" class="btn btn-primary">Submit</button>
                    </div>
                </div>
            </div>
        </div>

</form>

我的解决方案

看起来您不需要自定义验证器。订阅复选框然后根据复选框的值更新表单更容易。这是我现在的组件代码:

export class RegistrationComponent implements OnInit {
  registerForm: FormGroup;
  bool:boolean = false;
  constructor(private formBuilder: FormBuilder) {
    this.registerForm = this.formBuilder.group({
      name:['',[Validators.required,Validators.minLength(2)]],
      firstName:['',[Validators.required,Validators.minLength(2)]],
      email:['', [Validators.required,Validators.minLength(2)]],
      telephone:['',[Validators.required,Validators.minLength(9)]],
      mobilePhone:['',Validators.minLength(10)],
      type:[''],
      checkbox:[false],
      companyName:['',Validators.minLength(2)],
      rizivNumber:[''],
      taxNumber:['',Validators.minLength(2)],
      streetName:['', Validators.required],
      houseNumber:[''],
      bus:[''],
      zipCode:['',[Validators.required,Validators.minLength(4)]],
      place:['',[Validators.required,Validators.minLength(2)]]
    })
    this.formControlValueChanged();
   }

   setNotification(): void {
    this.bool = !this.bool;
    if(this.bool){
      this.registerForm.root.get('houseNumber').setValidators(Validators.required);
    }else{
      this.registerForm.root.get('houseNumber').clearValidators();
    }
    this.registerForm.get('houseNumber').updateValueAndValidity();
  }

  ngOnInit() {
  }

  formControlValueChanged() {
    this.registerForm.get('checkbox').valueChanges.subscribe(
        (mode: string) => {
            this.setNotification();
        });
}
}

【问题讨论】:

  • 你现在遇到什么错误?
  • 没有 .value 没有错误。它只是不起作用:带有.value错误:ncaught(承诺):TypeError:无法读取null的属性“值” TypeError:无法在FormControl.validateCheckbox [作为验证器]读取null的属性“值”
  • const check = control.root.get('checkbox:checked'); 试试这个。
  • 您无法访问另一个表单控件表单自定义验证器,您必须创建表单组验证器

标签: angular validation


【解决方案1】:

我在下面做了类似的事情:

仅当Send Notifications 单选按钮设置为文本时,我才需要电话。

我使用以下代码进行此操作:

  setNotification(notifyVia: string): void {
    const phoneControl = this.customerForm.get('phone');
    if (notifyVia === 'text') {
      phoneControl.setValidators(Validators.required);
    } else {
      phoneControl.clearValidators();
    }
    phoneControl.updateValueAndValidity();
  }

因此,这不是构建验证器,而是简单地在字段上添加或清除所需的验证器。在我的示例中,我只为一个控件 (phoneControl) 设置了验证器,但您可以轻松地为任意数量的控件设置验证器。

每次单选按钮更改时都会调用此代码,使用代码如下所示。每次选中复选框时,您都需要调用 setNotification:

this.customerForm.get('notification').valueChanges
  .subscribe(value => this.setNotification(value));

【讨论】:

  • 这将解决问题,但clear Validators 将清除来自控制的所有其他验证器
  • 在哪里设置订阅按钮的解码代码?目前正在尝试您的解决方案。
  • 我对您的代码进行了一些更改,现在可以使用了。谢谢您的帮助!将我的解决方案发布给其他人查看
  • @JorenVermeir 是的,这对你有用,但是 formGroup Validator 更干净,并且是返回验证错误而不是设置和清除验证的地方,这是我的观点
【解决方案2】:

您无法从自定义验证器访问另一个表单控件,您必须创建自定义表单验证器

export  function validateCheckbox(fg) {
  if (fg.get('checkbox').value) {
    let val = fg.get('text').value;
    if (val === null || val === undefined || val === '') {
      return {
        validate: {
          valid: false
        }
      };
    } else { // text control has a value
      return null;
    }
  } else { // checkbox value is false 
    return null;
  }
}

组件

  form: FormGroup;
  constructor(fb: FormBuilder) {
    this.form = fb.group({
      checkbox: [false],
      text: ['']
    }, { validator: validateCheckbox })
  }

stackblitz example

FormBuilder/Group

【讨论】:

  • 但是我如何只在复选框被选中时才使该字段成为必填项?
猜你喜欢
  • 1970-01-01
  • 2011-07-24
  • 2019-02-21
  • 2019-01-07
  • 2018-05-23
  • 2018-01-26
  • 2018-07-28
  • 1970-01-01
  • 2013-11-11
相关资源
最近更新 更多