美文网首页angular2Angular 4.x 修仙之路
ng-conf-2017 - Angular Form Vali

ng-conf-2017 - Angular Form Vali

作者: semlinker | 来源:发表于2017-06-18 12:48 被阅读56次

    目录

    • 第一节 - 验证概述
    • 第二节 - 设置基本的验证
    • 第三节 - 即将到来的验证功能

    第一节 - 验证概述

    overview-form-control

    同步验证器

    validator-fn

    同步验证器函数

    tambourineValidator(ctrl: AbstractControl): ValidationErrors | null {
      return ctrl.value === 'tambourine' ? null :
        {tambo: {expected: 'tambourine', actual: ctrl.value }};
    }
    

    异步验证器

    async-validator-fn

    异步验证器函数

    myAsyncValidator(ctrl: AbstractControl): Observable<ValidationErrors|null> {
      return this._http.get(`my/endpoint?username=${ctrl.value}`)
        .map(resp => resp.json().exists ? {exists: true} : null);
    }
    

    第二节 - 设置基本的验证

    json-server 简介

    json-server 用于基于 JSON 数据快速地创建本地模拟的 REST API。

    json-server 的安装

    $ npm install -g json-server
    

    json-server 的使用

    $ json-server --watch bids.json
    

    Angular CLI 代理配置

    创建 proxy.conf.json 文件

    {
      "/bids": {
        "target": "http://localhost:3000",
        "secure": false
      }
    }
    

    更新 package.json 文件

    {
      "scripts": {
        "start": "ng serve --proxy-config proxy.conf.json",
      }
    }
    

    创建 bids.json 文件

    {
      "bids": [
        {
          "id": 1,
          "name": "Semlinker",
          "bid": "10"
        }
      ]
    }
    

    同步验证与异步验证示例

    AppModule

    import { NgModule } from '@angular/core';
    import { BrowserModule } from '@angular/platform-browser';
    import {ReactiveFormsModule} from "@angular/forms";
    import {HttpModule} from "@angular/http";
    
    import { AppComponent } from './app.component';
    
    @NgModule({
      declarations: [
        AppComponent
      ],
      imports: [
        BrowserModule,
        HttpModule,
        ReactiveFormsModule
      ],
      providers: [
        {provide: 'config', useValue: {databaseURL: 'http://localhost:3000'}}
      ],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
    

    AppComponent

    import {Component, OnInit, Inject} from '@angular/core';
    import {FormGroup, FormControl, Validators, 
      AbstractControl, ValidationErrors} from "@angular/forms";
    import {Http} from "@angular/http";
    
    import {Observable} from "rxjs/Observable";
    import 'rxjs/add/operator/map';
    
    interface Bid {
      id: number;
      name: string;
      bid: number
    }
    
    @Component({
      selector: 'app-root',
      template: `
        <ul *ngIf="bids">
          <li *ngFor="let bid of bids">
            {{bid.name}}: {{bid.bid}}
          </li>
        </ul>
        <div>
           <p>New Bid</p>
           <form [formGroup]="form">
              <input type="text" placeholder="Name" 
                formControlName="name">
              <div class="errors" *ngIf="name.invalid && name.touched">
                Name is required.
              </div>
              <input type="number" placeholder="Bid" 
                formControlName="bid">
              <div class="errors" *ngIf="bid.invalid && bid.touched">
                <div *ngIf="bid.hasError('required')">Bid is required.</div>
                <div *ngIf="bid.hasError('toolow')">
                  Bid is too low, expect {{bid.errors.toolow.expected}}, current value is 
                  {{bid.value}}.
                </div>
              </div>
           </form>
        </div>
        <hr>
        <button (click)="post()" [disabled]="form.invalid">POST BID</button>
      `,
      styles: [`
        input.ng-invalid.ng-touched {
          border-left: 5px solid red;
        }
        
        input.ng-valid.ng-touched {
          border-left: 5px solid forestgreen;
        }
      `]
    })
    export class AppComponent implements OnInit{
      bids: Bid[];
    
      form = new FormGroup({
        name: new FormControl('', Validators.required),
        bid: new FormControl('', Validators.required, this.minimumBid.bind(this))
      });
    
      constructor(
        private _http: Http, 
        @Inject('config')private config) {
      }
    
      ngOnInit() {
        this._http.get(`${this.config.databaseURL}/bids`)
          .map(resp => resp.json())
          .subscribe( res => this.bids = res)
      }
    
     // 异步验证器
      minimumBid(ctrl: AbstractControl): Observable<ValidationErrors|null> {
        return this._http.get(`${this.config.databaseURL}/bids`)
          .map(resp => resp.json())
          .map(bids => bids[bids.length - 1])
          .map(bid => {
            return ctrl.value > bid.bid ? null : {toolow: {expected: bid.bid}}
          });
      }
    
      get name() { return this.form.get('name'); }
    
      get bid() { return this.form.get('bid'); }
    
     // 新增Bid
      post() {
        let newBid = {...this.form.value, id: ++this.bids[this.bids.length - 1].id};
        this._http.post(`${this.config.databaseURL}/bids`, newBid)
          .map(resp => resp.json())
          .subscribe(resp => {
            this.bids.push(resp);
          });
        this.form.reset();
      }
    }
    

    第三节 - 即将到来的验证功能

    验证流程

    validation-process

    流程一

    validation-process-1

    流程二

    validation-process-2

    验证管线

    validation-pipeline

    基于上面的内容我们能做什么

    • 定制验证器链
    • 控制验证顺序和验证时间
    • 当应用程序出现错误时,发出错误信息
    • 基于 Push 验证

    定制验证器链示例

    // ValidatorChain 目前还不支持
    export class AppComponent implements OnInit{
      bids: Bid[];
    
      form = new FormGroup({
        name: new FormControl('', Validators.required),
        bid: new FormControl('', {chain: this.myChain.bind(this)})
      });
    
      myChain(ctrl: AbstractControl): ValidatorChain {
        return (obs) => {
            return obs.map(Validators.required)
              .switchMap(errs => errs ? Observable.of(errs) : 
                this.minimumBid(ctrl)).startWith(PENDING)
      }
    }
    

    相关文章

      网友评论

        本文标题:ng-conf-2017 - Angular Form Vali

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