美文网首页
Angular2表单-自定义验证器

Angular2表单-自定义验证器

作者: 我是上帝可爱多 | 来源:发表于2017-07-28 11:50 被阅读189次

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

<form class="form-horizontal" [formGroup]="userForm" (ngSubmit)="logForm()">
        <div class="form-group">
            <button class="btn btn-default pull-right" (click)="reset()">重置</button>
        </div>
        <div class="form-group">
            <label class="col-sm-2 control-label">姓名:</label>
            <div class="col-sm-10">
                <input class="form-control" type="text" formControlName="name">
                <span *ngIf="userForm.controls.name.pristine" class="label label-primary">未修改</span>
                <span *ngIf="userForm.controls.name.dirty" class="label label-warning">已修改</span>
                <span *ngIf="userForm.controls.name.valid" class="label label-success">有效</span>
                <div [hidden]="userForm.controls.name.valid || userForm.controls.name.pristine" class="alert alert-danger">
                    <p *ngIf="userForm.controls.name.errors?.minlength">姓名最小长度为3</p>
                    <p *ngIf="userForm.controls.name.errors?.required">必须输入姓名</p>
                </div>
            </div>
        </div>
</form>

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

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

 <form class="form-horizontal" [formGroup]="userForm" (ngSubmit)="logForm()">
        <div class="form-group">
            <button class="btn btn-default pull-right" (click)="reset()">重置</button>
        </div>
        <div class="form-group">
            <label class="col-sm-2 control-label">姓名:</label>
            <div class="col-sm-10">
                <input class="form-control" type="text" formControlName="name">
                <span *ngIf="userForm.controls.name.pristine" class="label label-primary">未修改</span>
                <span *ngIf="userForm.controls.name.dirty" class="label label-warning">已修改</span>
                <span *ngIf="userForm.controls.name.valid" class="label label-success">有效</span>
                <div [hidden]="userForm.controls.name.valid || userForm.controls.name.pristine" class="alert alert-danger">
                    <p *ngIf="userForm.controls.name.errors?.minlength">姓名最小长度为3</p>
                    <p *ngIf="userForm.controls.name.errors?.required">必须输入姓名</p>
                </div>
            </div>
        </div>
        <div class="form-group">
            <label class="col-sm-2 control-label">电话:</label>
            <div class="col-sm-10">
                <input class="form-control" type="text" formControlName="mobile">
                <span *ngIf="userForm.controls.mobile.pristine" class="label label-primary">未修改</span>
                <span *ngIf="userForm.controls.mobile.dirty" class="label label-warning">已修改</span>
                <span *ngIf="userForm.controls.mobile.valid" class="label label-success">有效</span>
                <div [hidden]="userForm.controls.mobile.valid || userForm.controls.mobile.pristine" class="alert alert-danger">
                    <p *ngIf="userForm.controls.mobile.errors?.minlength || userForm.controls.mobile.errors?.maxlength">电话长度必须为11</p>
                    <p *ngIf="userForm.controls.mobile.errors?.required">必须输入电话</p>
                    <p *ngIf="userForm.controls.mobile.errors?.validateMobile">电话号码格式不正确</p>
                </div>
            </div>
        </div>
</form>

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

 <span *ngIf="userForm.controls.name.valid" class="label label-success">有效</span>
  // 如果表单name控件值是valid,有效就会显示。
  <p *ngIf="userForm.controls.name.errors?.minlength">姓名最小长度为3</p>
 // 如果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$ = <FormGroup>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就很清楚了。

<fieldset formGroupName="address">
            <div class="form-group">
                <label class="col-sm-2 control-label">城市:</label>
                <div class="col-sm-10">
                    <input class="form-control" type="text" formControlName="city">
                    <div [hidden]="userForm.controls.address.controls.city.valid || userForm.controls.address.controls.city.pristine" class="alert alert-danger">
                        <p *ngIf="userForm.controls.address.controls.city.errors?.required">必须输入城市</p>
                    </div>
                </div>
            </div>
            <div class="form-group">
                <label class="col-sm-2 control-label">街道:</label>
                <div class="col-sm-10">
                    <input class="form-control" type="text" formControlName="street">
                </div>
            </div>
        </fieldset>

上面这段代码一看就清楚了是不是,注意的是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$ = <FormGroup>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$ = <FormGroup>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里面引入的

<p *ngIf="userForm.controls.mobile.errors?.validateMobile">电话号码格式不正确</p>
对应的是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里面都可以引入使用。需要注意的是
<p *ngIf="userForm.controls.mobile.errors?.validateMobile">电话号码格式不正确</p>
.validateMobile 要和return值的{}里面的保持一致。好了,这期就先到这里。。。

相关文章

  • vue+element 表单验证问题

    常规表单验证、自定义表单验证、动态增删表单验证 1.常规表单验证 2.自定义表单验证 3.动态增减 a.表单 b.表格

  • Angular2表单-自定义验证器

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

  • Ionic2使用FormBuilder和Validators进行

    ionic2中的form表单是验证方式是基于angular2的form验证,在angular2的form经过更新后...

  • 15.《Angular表单校验》

    一、使用Angular自带的表单校验器 运行结果: 二、自定义表单校验器 当然我们也可以将验证器方法独立出来 使用...

  • 表单相关

    1.自定义验证器 1.1 行内验证器 当表单类中包含以'validate_字段属性名'形式命名的方法时,在验证字段...

  • 表单验证与回填以及表单常见bug解决方法

    表单的验证 正则验证 pattern 自定义验证validator 表单注意事项 ~获取值,使用getField...

  • 验证

    验证 表单请求验证类 必须 使用 表单请求 - FormRequest 类 来处理控制器里的表单验证。 验证类的 ...

  • 【Vue3+Vite+TS】13.0 组件十:强大的表单组件(上

    功能 可配置型表单,通过json对象的方式自动生成表单 具备更完善的功能:表单验证、自定义验证规则、动态删减表单、...

  • Django 框架之 自定义Forms

    知识点 如何自定义表单 表单验证 简介 参考文档 代码地址:Spareibs的Github 实验步骤 非自定义表单...

  • Jquery validation

    前端表单验证框架 页面引入 默认校验规则 封装后检验器 自定义rules举例(校验用户长度等) Example

网友评论

      本文标题:Angular2表单-自定义验证器

      本文链接:https://www.haomeiwen.com/subject/xydxlxtx.html