使用Event由template表單傳送資料給Component
利用事件的$event去傳送相關資訊給component
<input (keyup)="onKey($event)"> <p>{{values}}</p>
接收則可以透過event.target去存取該htmlInputElement的資料(詳細資料請見此)
下面的範例能將value存至一個變數內且顯示在頁面上:
export class KeyUpComponent_v1 { values = ''; onKey(event: any) { // without type info this.values += event.target.value + ' | '; } }
模版驅動的表單
使用模版驅動的表單需要在app.module.ts裡面宣告我們要使用FormsModule這個library,宣告方式如下
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms';//使用模版表單驅動需要import這個模組 import { AppComponent } from './app.component'; import { HeroFormComponent } from './hero-form/hero-form.component'; @NgModule({ imports: [ BrowserModule, FormsModule//在@ngModule裡去加上這個模組,這使應用程序可以訪問所有模板驅動的表單功能,包括。@NgModule、ngModel ], declarations: [ AppComponent, HeroFormComponent ], providers: [], bootstrap: [ AppComponent ] }) export class AppModule { }
使用ngModel對input的值與controller裡的變數做雙向繫結
下面這段code最主要要看的是[(ngModel)]="model.name"
,用這個標籤會自動將使用者輸入此input的值雙向綁定到model.name上面。
<input type="text" class="form-control" id="name" required [(ngModel)]="model.name" name="name"> 你所輸入的資料是: {{model.name}}
然後在component也要有model這個屬性才能夠被綁定
export class HeroFormComponent { model ={}; }
成果如下:
ngModel會附加的class
狀態(State ) | Class if true | Class if false |
---|---|---|
被點擊接觸過 | ng-touched | ng-untouched |
值被改變 | ng-dirty | ng-pristine |
值不符合驗證 | ng-valid | ng-invalid |
可以用下面的範例來觀察input元素class名稱的改變(#spy代表將這個input存到一個叫做spy的變數內)
<input type="text" class="form-control" id="name" required [(ngModel)]="model.name" name="name" #spy> <br />TODO: remove this: {{spy.className}}
下面是類別改變的狀態表
Show and hide validation error messages
在做表單驗證時,時常會有如下圖這樣的需求
若要使用表單驗證,需要在input宣告ngModel(不論有沒有做雙向綁定),或者宣告formControlName或formControl,不然無法驗證。
下面是一個最簡單的required驗證宣告:
<input name="fullName" ngModel required>
如果要用客製化的訊息去告訴使用者那邊輸入錯誤的話,則可以將ngModel的值輸出成一個模版變數#name
<label for="name">Name</label> <input type="text" class="form-control" id="name" required [(ngModel)]="model.name" name="name" #name="ngModel">
在上面我們看到#name="ngModel"
,這是因為ngModel這個directive的exportAs的值剛好就是ngModel。
這代表將input的ngModel存進一個叫做name的變數裡,下面就可以使用這個ngModel的模型顯示相關的錯誤訊息。
<div [hidden]="name.valid || name.pristine" class="alert alert-danger"> Name is required </div>
pristine的意思是未被改變過的,而name.valid則是檢查所有我們所設定的驗證器,回傳是否合法或者不合法。
因此[hidden]="name.valid || name.pristine"
的意思就是如果尚未填到該選項或者填入的值是合法的,則不顯示錯誤訊息。
現成的forms Validator
在上面的例子中,我們在input中下了required
來做必填欄位的驗證。
required是一個directive,我們可以在這邊看到這個directive的詳細使用說明。
在說明網頁中,有幾個是需要去看的,首先就是selector,代表我們要如何去使用這個驗證器。
以required為例,有三種選擇required的方法如下圖:
這個圖代表了required不能用在checkbox,要使用這個directive要在input上加上required以及ngModel(或者formControl, formControlName)屬性。
其他Angular有提供的驗證器如下
- CheckboxRequiredValidator:checkbox必填驗證器
- EmailValidator:e-mail格式驗證器
- MaxLengthValidator:最長字元數驗證
- MinLengthValidator:最短字元數驗證
- PatternValidator:可以用一串regular expression來驗證輸入的字串是否合法
- RequiredValidator:非checkbox的必填驗證器
客製化模板驅動表格驗證器
除了上述的內建驗證器之外,我們也可以自己製作自製的驗證器directive
@Directive({ selector: '[forbiddenName]', providers: [{provide: NG_VALIDATORS, useExisting: ForbiddenValidatorDirective, multi: true}] }) export class ForbiddenValidatorDirective implements Validator { @Input() forbiddenName: string; validate(control: AbstractControl): {[key: string]: any} { return this.forbiddenName ? forbiddenNameValidator(new RegExp(this.forbiddenName, 'i'))(control) : null; } }
在使用上的部份,就可以直接像下面這樣
<input id="name" name="name" class="form-control" required minlength="2" forbiddenName="bob" [(ngModel)]="hero.name" #name="ngModel" > <div *ngIf="name.errors.forbiddenName"> Name cannot be Bob. </div>
要注意的是,官網範例forbidden-name.directive.ts的selector名稱寫錯,不能使用appForbiddenName,要用forbiddenName,才能對的起來
這邊有ISSUE回報: Custom Validator example on angular.io directive selector issue.
詳情請見線上範例:live example
使用ngSubmit送出表單
在ngForm裡面,submit的button按下後並不會直接發生任何事,而是會觸發一個ngSubmit的事件,因此需要在form的地方去註冊ngSubmit事件
<form (ngSubmit)="onSubmit()" #heroForm="ngForm">
在上面的程式碼裡,我們將這個表單ngForm存至heroForm這個變數裡,因此在submit的按鈕可以存取ngForm裡的值來判段這個表單是否已通過驗證
<button type="submit" class="btn btn-success" [disabled]="!heroForm.form.valid">Submit</button>