目錄css
一:校驗表單的使用html
1.搭建腳手架git
2.校驗表單的使用github
3.select下拉列表的用法npm
對於CRUD型的應用,表單是必備組件。bootstrap
1.搭建腳手架數組
git clone https://github.com/mgechev/switching-to-angular2.git form1瀏覽器
npm installangular2
npm startapp
app目錄刪掉全部內容後,新建form目錄,form目錄建立index.html和app.ts
index.html是默認內容。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title><%= TITLE %></title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css"> <!-- inject:css --> <!-- endinject --> </head> <body> <app>Loading...</app> <!-- inject:js --> <!-- endinject --> <%= INIT %> </body> </html>
app.ts只是簡單的App組件和啓動函數。
import {Component} from '@angular/core'; import {bootstrap} from '@angular/platform-browser-dynamic'; @Component({ selector: 'app', template: ` <div>初始狀態</div> ` }) class App {} bootstrap(App);
打開http://localhost:5555/dist/dev/form/,可看見預先填寫的字符串。
準備就緒!
2.校驗表單的使用
分爲3個部分:
第一部分:表單指令集和PROVIDERS引入,以及裝飾器準備
import{FORM_DIRECTIVES,FORM_PROVIDERS} from '@angular/common';
FORM_DIRECTIVES是表單指令集,
FORM_PROVIDERS是內置的PROVIDERS數組。
組件要使用導入的內容,那麼裝飾器就要提供相應的屬性。
@Component({ selector: 'app', templateUrl:"./app.html", styles:[], directives:[FORM_DIRECTIVES], providers:[FORM_PROVIDERS] })
第二部分:form標籤使用ngForm指令
<form #f="ngForm" (ngSubmit)="login()"> <!--名稱爲f的表單,可用來引用當前form--> </form>
當angular2發現這樣的form標籤,並且含有ngForm指令,就會把它當作form指令來加強了。 (ngSubmit)="login()" 固然是提交咯。
第三部分:對input等進行表單校驗
<form #f="ngForm" (ngSubmit)="login()"> <input id="nameInput" type="text" required ngControl="nameInput" minlength="6" maxlength="11"/> </form>
這裏使用的ngControl指令會在表單的值發生改變時進行校驗,同時爲校驗的不一樣階段添加class類,還會擴展required屬性的語義,
form不一樣的class類:
ng-untouched。控件尚未被訪問過。
ng-touched。控件已經被訪問過。
ng-pristine。控件的值沒有被修改。
ng-dirty。控件的值已經被修改過。
ng-valid。控件上所綁定的全部校驗器都返回了true。
ng-invalid。控件上所綁定的某個校驗器返回了false。
好比
app.html:
<form #f="ngForm" (ngSubmit)="login()"> <lable>用戶名:</lable> <br/> <input id="nameInput" type="text" required ngControl="name" minlength="11" maxlength="11"/> <br/> <span>調試打印:{{f.valid}}</span> </form>
app.ts:
import {Component} from '@angular/core'; import {bootstrap} from '@angular/platform-browser-dynamic'; import{FORM_DIRECTIVES,FORM_PROVIDERS} from '@angular/common'; @Component({ selector: 'app', templateUrl:"./app.html", styles: [ `input.ng-dirty.ng-invalid{ border:1px solid red; //邊框 }` ], directives:[FORM_DIRECTIVES], providers:[FORM_PROVIDERS] }) class App {} bootstrap(App);
因爲輸入不合法,會會有紅色邊框
3.select下拉列表的用法
咱們以組件的方式來開發這個select下拉列表。
首先,組件代碼都準備好。
app新建form-select目錄,目錄下建立app.html、app.ts、index.html。
相似
index.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title><%= TITLE %></title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css"> <!-- inject:css --> <!-- endinject --> </head> <body> <app>Loading...</app> <!-- inject:js --> <!-- endinject --> <%= INIT %> </body> </html>
注意,裏面有boostrap引入,因此能夠直接的使用bootstrap的樣式哦。
app.html:
import {Component} from '@angular/core'; import {bootstrap} from '@angular/platform-browser-dynamic'; import{FORM_DIRECTIVES,FORM_PROVIDERS} from '@angular/common'; @Component({ selector: 'app', templateUrl:"./app.html", styles: [ `select.ng-dirty.ng-invalid{ border:1px solid red; }` //若是不合法會有紅色的邊框 ], directives:[FORM_DIRECTIVES], providers:[FORM_PROVIDERS] }) class App { youLike:string[]=[ "艾莎","安娜","漢斯","阿倫黛爾" ] //冰雪奇緣的角色 } bootstrap(App);
首先使用ngFor指令把youLike數組遍歷到option選項中。
<select class="form-control"> <option *ngFor="#yL of youLike" [value]="yL"> {{yL}} </option> </select>
而後使用ngControl指令進行校驗,添加required屬性、使用ngModel得到選擇項。
<select class="form-control" required ngControl="youLike"[(ngModel)]="youLike"> <option *ngFor="#yL of youLikes" [value]="yL"> {{yL}} </option> </select> <span>調試:youLike選擇項是{{youLike}}</span>
瀏覽器顯示結果
1.自定義控件的校驗器
雖然angular2提供了一組預約義好的校驗器,可是並不能覆蓋各類各樣的格式。這裏咱們自定義一個email校驗器。
Step1:寫好校驗函數
校驗函數接收value值爲參數,沒有值或者不匹配,返回null,不然返回{"invalidEmail":true}。
function validateEmail(emailControl){ var emailReg=/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/; //正則 if(!emailControl||emailReg.test(emailControl.value)){ return null; }else{ return {"invalidEmail":true} } }
step2:把校驗函數包裝到指令中。
import {NG_VALIDATORS} from "@angular/common"; import {Directive} from "@angular/core"; //引入NG_VALIDATORS和Directive @Directive({ selector:"[email-input]", //校驗指令定義成屬性 providers: [{ provide: NG_VALIDATORS, useValue: validateEmail, multi: true }] //使用NG_VALIDATORS定義了單個provider,咱們注射了綁定的值。 }) class EmailValidator{ }
step3:email控件上增長email-input屬性。
<input id="emailInput" class="form-control" email-input type="text" ngControl="email" [(ngModel)]="email"/>
step4:到組件上掛載email-input指令。
@Component({ selector: 'app', templateUrl:"./app.html", styles: [ `input.ng-dirty.ng-invalid{ border:1px solid red; }` ], directives:[FORM_DIRECTIVES,EmailValidator], //EmailValidator指令添加到指令選項,就可使用了 providers:[FORM_PROVIDERS] }) class App {}
打開http://localhost:5555/dist/dev/email-validate/
完整的app.ts代碼:
ch7-forms/form1/app/email-validate/app.ts:
import {Component} from '@angular/core'; import {bootstrap} from '@angular/platform-browser-dynamic'; import{FORM_DIRECTIVES,FORM_PROVIDERS} from '@angular/common'; import {NG_VALIDATORS} from "@angular/common"; import {Directive} from "@angular/core"; //引入NG_VALIDATORS和Directive function validateEmail(emailControl){ var emailReg=/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/; if(!emailControl||emailReg.test(emailControl.value)){ return null; }else{ return {"invalidEmail":true} } } @Directive({ selector:"[email-input]", //校驗指令定義成屬性 providers: [{ provide: NG_VALIDATORS, useValue: validateEmail, multi: true }] //使用NG_VALIDATORS定義了單個provider,咱們注射了綁定的值。 }) class EmailValidator{ } @Component({ selector: 'app', templateUrl:"./app.html", styles: [ `input.ng-dirty.ng-invalid{ border:1px solid red; }` ], directives:[FORM_DIRECTIVES,EmailValidator], providers:[FORM_PROVIDERS] }) class App {} bootstrap(App);
2.ngForm指令
新建ng-form目錄,目錄下建立index.html、app.ts、app.html。
index.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title><%= TITLE %></title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css"> <!-- inject:css --> <!-- endinject --> </head> <body> <app>Loading...</app> <!-- inject:js --> <!-- endinject --> <%= INIT %> </body> </html>
app.html暫時還使用以前的form代碼:
<form #f="ngForm" (ngSubmit)="login()"> <lable>用戶名:</lable> <br/> <input id="nameInput" type="text" required ngControl="name" minlength="11" maxlength="11"/> <br/> <span>調試打印:{{f.valid}}</span> </form>
app.ts暫時使用以前的代碼:
import {Component} from '@angular/core'; import {bootstrap} from '@angular/platform-browser-dynamic'; import{FORM_DIRECTIVES,FORM_PROVIDERS} from '@angular/common'; @Component({ selector: 'app', templateUrl:"./app.html", styles: [ `input.ng-dirty.ng-invalid{ border:1px solid red; }` ], directives:[FORM_DIRECTIVES], providers:[FORM_PROVIDERS] }) class App {} bootstrap(App);
打開http://localhost:5555/dist/dev/ng-form/,會有以下結果
如今爲了演示form元素的用法,定義control-error組件,用來顯示報錯信息。
step1:定義ControlErrors組件
import{NgControl,NgForm} from "@angular/common"; import{Host} from "@angular/core" //NgControl類是一個抽象類,用來表明angular表單 //Host是一個裝飾器,與依賴注入有關 @Component({ template: `<div>{{currentError}}</div>`, selector: 'control-errors', inputs: ['control', 'errors'] }) //組件的輸入是control和errors class ControlErrors { errors: Object; control: string; constructor(@Host() private formDir: NgForm) {} get currentError() { let control = this.formDir.controls[this.control]; let errorMessages = []; if (control && control.touched) { errorMessages = Object.keys(this.errors) .map(k => control.hasError(k) ? this.errors[k] : null) .filter(error => !!error); } return errorMessages.pop(); } }
step2:組件註冊
@Component({ selector: 'app', templateUrl:"./app.html", styles: [ `input.ng-dirty.ng-invalid{ border:1px solid red; }` ], directives:[FORM_DIRECTIVES,ControlErrors], //組件註冊 providers:[FORM_PROVIDERS ] }) class App { }
step3:使用control-errors組件
<form #f="ngForm" > <div class="form-group"> <label class="control-label" for="realNameInput">Real name</label> <div> <input id="realNameInput" class="form-control" type="text" ngControl="name" required maxlength="5"> <control-errors control="name" [errors]="{ 'required': 'Real name is required', 'maxlength': 'The maximum length of the real name is 5characters' }"></control-errors> </div> </div> </form>
打開http://localhost:5555/dist/dev/ng-form/,使得input框得到焦點,而後失去焦點,瀏覽器結果如圖
OK!
最終完整的代碼:
app.html:
<form #f="ngForm" > <div class="form-group"> <label class="control-label" for="realNameInput">Real name</label> <div> <input id="realNameInput" class="form-control" type="text" ngControl="name" required maxlength="5"> <control-errors control="name" [errors]="{ 'required': 'Real name is required', 'maxlength': 'The maximum length of the real name is 5characters' }"></control-errors> </div> </div> </form>
app.ts:
import {Component} from '@angular/core'; import {bootstrap} from '@angular/platform-browser-dynamic'; import{FORM_DIRECTIVES,FORM_PROVIDERS} from '@angular/common'; @Component({ selector: 'app', templateUrl:"./app.html", styles: [ `input.ng-dirty.ng-invalid{ border:1px solid red; }` ], directives:[FORM_DIRECTIVES], providers:[FORM_PROVIDERS] }) class App {} bootstrap(App);
index.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title><%= TITLE %></title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css"> <!-- inject:css --> <!-- endinject --> </head> <body> <app>Loading...</app> <!-- inject:js --> <!-- endinject --> <%= INIT %> </body> </html>
3.雙向數據綁定
ngModel指令輕鬆實現雙向數據綁定。選擇器爲[(ngModel)]。
目錄結構
ch7-forms/form1/app/ng-model/app.ts:
import {Component} from '@angular/core'; import {bootstrap} from '@angular/platform-browser-dynamic'; import{NgModel} from "@angular/common"; @Component({ selector: 'app', templateUrl:"./app.html", directives:[NgModel] }) class App { name:string; } bootstrap(App); //很是簡單的例子
ch7-forms/form1/app/ng-model/app.html:
<input type="text" [(ngModel)]="name"/> <div>{{name}}</div>
ch7-forms/form1/app/ng-model/index.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title><%= TITLE %></title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css"> <!-- inject:css --> <!-- endinject --> </head> <body> <app>Loading...</app> <!-- inject:js --> <!-- endinject --> <%= INIT %> </body> </html>
打開http://localhost:5555/dist/dev/ng-model/,瀏覽器結果如圖,當修改了input的值,label會自動刷新。
表單數據不少,並不是一兩個,咱們能夠經過把數據以屬性的形式掛載到某個對象(實例上),作很是簡潔的存儲。
只作一個簡單的例子:
ch7-forms/form1/app/user/app.html:
<input type="text" [(ngModel)]="user.name"/> <button (click)="getUser(user)">得到user對象</button>
ch7-forms/form1/app/user/user.ts:
export class User{ name:string; } //數據從logic分離出來了 //實際狀況會有更多的屬性
ch7-forms/form1/app/user/app.ts:
//頂級組件的代碼 import {Component} from '@angular/core'; import {bootstrap} from '@angular/platform-browser-dynamic'; import{NgModel} from "@angular/common"; import{User}from "./user"; @Component({ selector: 'app', templateUrl:"./app.html", directives:[NgModel] }) class App { user=new User(); getUser(user){ console.log(user) } } bootstrap(App);
ch7-forms/form1/app/user/index.html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title><%= TITLE %></title> <meta name="description" content=""> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css"> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css"> <!-- inject:css --> <!-- endinject --> </head> <body> <app>Loading...</app> <!-- inject:js --> <!-- endinject --> <%= INIT %> </body> </html>
當input框輸入值以後,會打印對象
另外關於提交有一個小方法阻止重複提交。
<form #f="ngForm" (ngSubmit)="login()" [hidden]="submitted"> </form>
一開始設置submitted爲false,那麼表單就能夠經過login來提交了,而一旦提交完成,設置爲true,那麼就隱藏起form,也就不會有再次提交了。妙!