YouTube 地址:ng-conf-2017 - Angular Form Validation
Google Doc:PPTgit
第一節 - 驗證概述github
第二節 - 設置基本的驗證typescript
第三節 - 即將到來的驗證功能shell
tambourineValidator(ctrl: AbstractControl): ValidationErrors | null { return ctrl.value === 'tambourine' ? null : {tambo: {expected: 'tambourine', actual: ctrl.value }}; }
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 數據快速地建立本地模擬的 REST
API。npm
$ npm install -g json-server
$ json-server --watch bids.json
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" } ] }
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 { }
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(); } }
定製驗證器鏈json
控制驗證順序和驗證時間bootstrap
當應用程序出現錯誤時,發出錯誤信息app
基於 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) } }