angularjs2 学习笔记(六) Form

Angular 2 Form表单

在angular2 form表单中咱们须要了解表单数据绑定、数据验证、数据提交等内容,在下面的示例中并无实际提交到后台,这部份内容在从此webapi中加以练习。html

表单创建

<form (ngSubmit)="onSubmit(planetForm.value)" #planetform="ngForm">html5

</form>web

这里是一个空的表单ngSubmit是一个事件,用于提交数据,数据则是整个form表单的内容,一般状况下咱们的表单会绑定到咱们的一个model中,那么提交的数据最后也是以json格式返回到后台来处理。json

在表单中咱们可使用标准的html5控件来处理用户输入。bootstrap

数据绑定

<div class="form-group">api

        <label class="col-xs-4 control-label" for="id">id : </label>promise

        <div class="col-xs-8">angular2

            <input type="text" style="width: 300px" class="form-control" required异步

                   [(ngModel)]="myPlanet.id"编辑器

                   ngControl="id"

                   #planetid="ngForm">

            <div [hidden]="planetid.valid || planetid.pristine" class="alert alert-danger">

                The Name of green car is required !

            </div>

        </div>

    </div>

这个一个表单输入的内容其中使用的是bootstrap的表单样式,在input中咱们使用[(ngModel)](注意大小写)实现双向绑定,ngControl用于检测数据变化对应的是model中的字段,设置input的变量为ngForm来告诉angular 这个输入是这个表单内容。在vs中因为默认设置在粘贴html文本时会自动将大写字母变化成小写字母,因此angular的某些标签很容易发生错误,因此须要关闭这个自动转换,方法就是在vs的选项中将文本编辑器中的html高级选项下的粘贴时设置格式设置为false。

数据验证

html5内置的数据验证包括Required、minLength、maxLength、pattern ,咱们能够将这些标签应用到咱们的输入控件上,如

<input type="text" style="width: 300px" class="form-control" required maxlength="10" minLength="4"

                   [(ngModel)]="myPlanet.id"

                   ngControl="name"

                   #planetid="ngForm">

            <div [hidden]="planetid.valid || planetid.pristine" class="alert alert-danger">

                The id is required !

            </div>

这里的"planetid.valid || planetid.pristine是验证这个input输入是否有效,或者数据是否改变。

Formbuilder

Formbuilder是咱们能够采用的另外一种方式来建立Form,这种方式是以模型驱动完成的,更适合咱们进行编码控制,有利于咱们将逻辑与视图分离。

Angular2 form 做用机制由两个主要的组件Controls和Controls group。

Control:包含值和验证状态,一个control可以被邦定能够包含三个可选参数(缺省值,验证,异步验证),例如

this.username = new Control('Default value', Validators.required, usernameValidator.checkIfAvailable);

在html应用时使用ngControl标签绑定这个控件

<input required type=”text” ngControl=”username” />

 

这里定义的username与input中ngControl指定的名称要一致。

Control Groups:form定义的一部分,经过将多个cotrol组合在一块儿造成组。

class App {
 
 name: Control;
 username: Control;
 email: Control;
 
 form: ControlGroup;
 
 constructor(private builder: FormBuilder) {
 
   this.name = new Control('', Validators.required);
   this.email = new Control('', Validators.required);
   this.username = new Control('', Validators.required);
 
   this.form = builder.group({
     name: this.name,
     email: this.email,
     username: this.username
   });
 }

};

html应用时加入ngFormModel来标识。

<form [ngFormModel]=”form”>

自定义验证

除了内置验证外,咱们还能够自定义验证,例子以下

import {Control} from 'angular2/common';

interface ValidationResult

{

    [key: string]: boolean;

}

export class UsernameValidator

{

 

    static startsWithNumber( control: Control ): ValidationResult

    {

 

        if ( control.value !="" && !isNaN( control.value.charAt( 0 ) ) ){

            return { "startsWithNumber": true };

        }

 

        return null;

    }

 

}

这个自定义验证若是输入的值中首字母是数字则验证无效,返回null则验证经过。使用方法

首先import {UsernameValidator} from './customValidate';

而后在咱们须要验证的控件上加入自定义验证

this.name = new Control( this.myPlanet.name, UsernameValidator.startsWithNumber );

错误提示

<div *ngIf="name.dirty && !name.valid">

  <p *ngIf="name.errors.startsWithNumber">

    Your name can't start with a number

  </p>

</div>

这里的errors. startsWithNumber就是咱们自定义返回的key值。最好的方式是使用hasError,由于若是返回的startsWithNumber是null的话会引起异常

<p *ngIf="name.hasError('startsWithNumber')">

异步验证

若是咱们须要使用service去到后台获取数据并验证,则咱们须要使用异步验证方式,这里的例子使用promise模拟。

static usernameTaken( control: Control ): Promise<ValidationResult>

    {

 

        let q = new Promise(( resolve, reject ) =>

        {

            setTimeout(() =>

            {

                if ( control.value !== 'oldkingsir') {

                resolve( { "usernameTaken": true});

            } else {

                resolve( null );

            }

        }, 1000 )

    });

 

   return q;

 }

真实应用多是

class ProductValidator {

    static productExists(control: Control): {[key: string]: any} {

        return new Promise( resolve => {

            var productService = new ProductService();

            var product: Product;

            productService.getProduct(control.value)

            .then(productFound => {

                if (productFound == null) {

                    // need to return something if not ok

                    resolve({productExists: false});

                } else {

                    // need to return null if ok

                    resolve(null);

                }

            });

        });

    }

}

下面须要使用验证的第三个参数,方式以下

this.name = new Control( this.myPlanet.name,UsernameValidator.startsWithNumber, UsernameValidator.usernameTaken );

html

<div *ngIf="name.dirty && !name.valid">

                <span *ngIf="name.pending">Checking istaken...</span>

                  <p *ngIf="name.hasError('startsWithNumber')">

                    Your name can't start with a number

                 </p>

                <p *ngIf="name.hasError('usernameTaken')">

                    Your name is already taken

                 </p>

            </div>

这里使用了pending来友好提示验证中。

组合验证

若是须要进行多个验证可使用compose组合验证,以下

this.name = new Control('', Validators.compose([Validators.required, Validators.minLength(4)]));

 

 

 

最后若是整个表单验证不经过咱们不提交则能够在提交按钮上加以处理,如

<button type="submit" class="btn btn-default" [disabled]="!form.valid">Submit</button>