Angular2表单-自定义验证器

前面angular已经做了2次专题了,今天我们继续学习,来看一下如何在表单中自定义验证控件。
下面是一段很长的html代码,算了我还是一步步来吧。。

未修改 已修改 有效

姓名最小长度为3

必须输入姓名

1.任何一个表单都会有[formGroup]="userForm"这样的字段,这个表单的获取就是通过‘userForm’
2.formControlName="name" 代表着个input是当前这个表单控件,获取它可以用:userForm.controls.name

有了上面的知识我先把完整的表单html代码拿出来

 
未修改 已修改 有效

姓名最小长度为3

必须输入姓名

未修改 已修改 有效

电话长度必须为11

必须输入电话

电话号码格式不正确

上面2个表单有2个控件,一个是name,一个是mobile,注意下面这段

 有效
  // 如果表单name控件值是valid,有效就会显示。
  

姓名最小长度为3

// 如果name长度小于minlength(3),会显示最小长度错误。

我们来看一下最重要的component.js是如何写的把,先看一下ngOninit如何初始化表单的

ngOnInit() {
        this.userForm = this.formBuilder.group({
            name: ['张三', [Validators.required, Validators.minLength(3)]],
            mobile: [13800138001, [Validators.required, Validators.minLength(11), Validators.maxLength(11), validateMobile]],
            address: this.formBuilder.group({
                city: ['北京', Validators.required],
                street: ['朝阳望京...', Validators.required]
            })
        });
        const addr$ = this.userForm.controls['address'];
        const city$ = addr$.controls['city'];
        const street$ = addr$.controls['street'];

        city$.valueChanges.debounceTime(1000).distinctUntilChanged().subscribe(cityValue => {
            this.msg = cityValue + ' 欢迎你!';
            street$.setValue(cityValue);
        });

        this.userForm.valueChanges.subscribe(x => this.changeMsg = { event: 'Form DATA CHANGED', object: x });
    }

我们下面来看一下formBuilder是干嘛的

this.userForm = this.formBuilder.group({
            name: ['张三', [Validators.required, Validators.minLength(3)]],
            mobile: [13800138001, [Validators.required, Validators.minLength(11), Validators.maxLength(11), validateMobile]],
            address: this.formBuilder.group({
                city: ['北京', Validators.required],
                street: ['朝阳望京...', Validators.required]
            })
        });

创建了3个表单控件:name mobile address,其中name的默认值是‘张三’,验证规则是[Validators.required, Validators.minLength(3)]
mobile也有验证规则,但是多了一个我们看不懂的validateMobile,等下再说,这就是我们自定义的验证指令。
可以看出来address下面有子控件city street ,那么我们来看这段html就很清楚了。

必须输入城市

上面这段代码一看就清楚了是不是,注意的是formBuilder的用法,如何创建表单控件。我们来看一下完整的ts文件把

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormControl, FormBuilder, Validators } from '@angular/forms';

import { validateMobile } from '../validators/mobile.validator';

@Component({
    selector: 'reactive-form',
    templateUrl: 'app/reactive-forms/reactive-forms.component.html',
    styleUrls: ['app/reactive-forms/reactive-forms.component.css']
})
export class ReactiveFormsComponent implements OnInit {
    userForm: FormGroup;
    msg: String;
    changeMsg: any;

    constructor(private formBuilder: FormBuilder) {}

    ngOnInit() {
        this.userForm = this.formBuilder.group({
            name: ['张三', [Validators.required, Validators.minLength(3)]],
            mobile: [13800138001, [Validators.required, Validators.minLength(11), Validators.maxLength(11), validateMobile]],
            address: this.formBuilder.group({
                city: ['北京', Validators.required],
                street: ['朝阳望京...', Validators.required]
            })
        });
        const addr$ = this.userForm.controls['address'];
        const city$ = addr$.controls['city'];
        const street$ = addr$.controls['street'];

        city$.valueChanges.debounceTime(1000).distinctUntilChanged().subscribe(cityValue => {
            this.msg = cityValue + ' 欢迎你!';
            street$.setValue(cityValue + ' 欢迎你!');
        });

        this.userForm.valueChanges.subscribe(x => this.changeMsg = { event: 'Form DATA CHANGED', object: x });
    }

    logForm(NgForm) {
        if (this.userForm.invalid) {
            this.msg = 'validation errors!';
        } else {
            this.msg = null;
        }
        console.log(this.userForm.value);
    }

    reset() {
        this.userForm.reset();
    }
 }

从上得出:

  • 表单必备引入的:formGroup formBuilder formControl Validators formGroup是表单的入口之处,formBuilder用于创建表单控件结构,formControl用于获取控件,validators是表单验证所需。

  • const addr$ = this.userForm.controls['address']; 对于这种带有子控件的控件需要用formGroup强转。 比如我们想获得name控件的值,就是this.userForm.controls['name'].value.

我们来看下这2段代码

city$.valueChanges.debounceTime(1000).distinctUntilChanged().subscribe(cityValue => {
            this.msg = cityValue + ' 欢迎你!';
            street$.setValue(cityValue + ' 欢迎你!');
        });
// 监听city控件输入值的改变,有1000ms延迟,同时street$.setValue(cityValue + ' 欢迎你!'); 就是street控件的值也会跟着改变。
 this.userForm.valueChanges.subscribe(x => this.changeMsg = { event: 'Form DATA CHANGED', object: x });
// 监控表单的变化,并作出反应,x是表单序列化后的值

其实我们一直想知道的是 mobile: [13800138001, [Validators.required, Validators.minLength(11), Validators.maxLength(11), validateMobile]]里面的这个validateMobile到底是啥。

import { FormControl, NG_VALIDATORS } from '@angular/forms';
import { Directive } from '@angular/core';

// 这不正好是校验电话的正则吗
export function validateMobile(c: FormControl) {
    let MOBILE_REGEXP = /^1[0-9]{10}$/;

    return MOBILE_REGEXP.test(c.value) ? null : {
        validateMobile: {valid: false}
    }
}

// 注意导出的validateMobile需要放在providers里面
@Directive({
    selector: '[validateMobile]',
    providers: [
        { provide: NG_VALIDATORS, useValue: validateMobile, multi: true }
    ]
})
export class MobileValidator {}
// 这个暴露的MobileValidator需要在app.module里引入

import { validateMobile } from '../validators/mobile.validator'; 这是我们在ts里面引入的

电话号码格式不正确

对应的是function validateMobile 后面的 validateMobile

注意需要在app.module中引入MobileValidator

@NgModule({
    imports:        [BrowserModule, FormsModule, ReactiveFormsModule, RouterModule.forRoot(routes)],
    declarations:   [AppComponent, TemplateFormsComponent, ReactiveFormsComponent, MobileValidator], // MobileValidator必须引入
    bootstrap:      [AppComponent]
})

其实我们可以在MobileValidator定义多个验证函数

import { FormControl, NG_VALIDATORS } from '@angular/forms';
import { Directive } from '@angular/core';

export function validateMobile1(c: FormControl) {
    let MOBILE_REGEXP = /^1[0-9]{13}$/;

    return MOBILE_REGEXP.test(c.value) ? null : {
        validateMobile1: {valid: false}
    }
}

export function validateMobile2(c: FormControl) {
    let MOBILE_REGEXP = /^1[0-5]{5}[0-9]{5}$/;

    return MOBILE_REGEXP.test(c.value) ? null : {
        validateMobile2: {valid: false}
    }
}


@Directive({
    selector: '[validateMobile]',  // 其实这个名字可以随便取
    providers: [
        { provide: NG_VALIDATORS, useValue: validateMobile1, multi: true },
        { provide: NG_VALIDATORS, useValue: validateMobile2, multi: true }
    ]
})
export class MobileValidator {}

如上上面定义了2个mobile验证规则,在component里面都可以引入使用。需要注意的是

电话号码格式不正确


.validateMobile 要和return值的{}里面的保持一致。好了,这期就先到这里。。。

你可能感兴趣的:(Angular2表单-自定义验证器)