表单

来源:互联网 发布:中国移动积分兑换软件 编辑:程序博客网 时间:2024/05/22 01:27

在这一章中,我们将学会如何
(1)使用组件和模板构造表单
(2)使用ngModel实现双向数据绑定
(3)结合表单来使用ngModel,用于读取和写入输入控件的值
(4)使用特殊的css类来跟踪控件状态,并提供强烈的视觉反馈
(5)向用户显示验证错误信息,以及启用/禁用表单控件
(6)利用模板引用变量在HTML中共享信息。

并按照以下步骤一步步构造表单
(1)创建Hero模型类
(2)创建控制此表单的组件
(3)创建具有初始表单的布局的模板
(4)使用NgModel双向绑定数据绑定语法把数据属性绑定到表单组件。
(5)往每个表单上输入控件添加name属性(attribute)
(6)添加自定义css来提供视觉反馈
(7)显示和隐藏有效性验证的错误信息
(8)使用ngSubmit处理表单提交
(9)禁用此表单的提交按钮,直到表单变为有效

一、创建Hero模型类

export class Hero {  constructor(    public id: number,    public name: string,    public power: string,    public alterEgo?: string  ) {  }}

二、创建表单组件
Angular表单分为两部分:基于HTML的模板和组件类,用来处理数据和用户交互。

import { Component } from '@angular/core';import { Hero }    from './hero';@Component({  moduleId: module.id,  selector: 'hero-form',  templateUrl: 'hero-form.component.html'})export class HeroFormComponent {  powers = ['Really Smart', 'Super Flexible',            'Super Hot', 'Weather Changer'];  model = new Hero(18, 'Dr IQ', this.powers[0], 'Chuck Overstreet');  submitted = false;  onSubmit() { this.submitted = true; }  // TODO: Remove this when we're done  get diagnostic() { return JSON.stringify(this.model); }}

二、修改app.module.ts
app.module.ts定义了应用的根模块,其中标识了即将用到的外部模块,以及声明属于本模块中的组件,例如HeroFormComponent。
因为模板驱动的表单位于他们自己的模块,所以在使用表单之前,需要将FormsModule添加到应用模块的imports数组中。

import { NgModule }      from '@angular/core';import { BrowserModule } from '@angular/platform-browser';import { FormsModule }   from '@angular/forms';import { AppComponent }  from './app.component';import { HeroFormComponent } from './hero-form.component';@NgModule({  imports: [    BrowserModule,    FormsModule  ],  declarations: [    AppComponent,    HeroFormComponent  ],  bootstrap: [ AppComponent ]})export class AppModule { }

如果组件、指令或者管道出现在模块的import数组中,不要把他声明在declarations中,如果是你自己写的,并且属于当前模块,就要把它声明在declaration中。

三、修改app.module.ts

import { Component } from '@angular/core';@Component({  selector: 'my-app',  template: '<hero-form></hero-form>'})export class AppComponent { }

四、创建初始HTML表单模板

<div class="container">    <h1>Hero Form</h1>    <form>      <div class="form-group">        <label for="name">Name</label>        <input type="text" class="form-control" id="name" required>      </div>      <div class="form-group">        <label for="alterEgo">Alter Ego</label>        <input type="text" class="form-control" id="alterEgo">      </div>      <button type="submit" class="btn btn-default">Submit</button>    </form></div>

五、用NgFor添加超能力
在表单中添加select,用ngFor把powers列表绑定到列表选项。

<div class="form-group">  <label for="power">Hero Power</label>  <select class="form-control" id="power" required>    <option *ngFor="let pow of powers" [value]="pow">{{pow}}</option>  </select></div>

六、使用ngModel进行双向数据绑定

<input type="text"  class="form-control" id="name"       required       [(ngModel)]="model.name" name="name">  TODO: remove this: {{model.name}}

注意,input标签还添加了name属性,并设置为name,使用任何唯一值都可以,在表单中使用ngModel时,必须要定义name属性。

在内部,Angular创建了一些FormControl,并把它们注册到NgForm指令,再将该指令附加到form标签,注册每个FormControl时,使用name属性值作为键值。

{{diagnostic}}<div class="form-group">  <label for="name">Name</label>  <input type="text" class="form-control" id="name"         required         [(ngModel)]="model.name" name="name"></div><div class="form-group">  <label for="alterEgo">Alter Ego</label>  <input type="text"  class="form-control" id="alterEgo"         [(ngModel)]="model.alterEgo" name="alterEgo"></div><div class="form-group">  <label for="power">Hero Power</label>  <select class="form-control"  id="power"          required          [(ngModel)]="model.power" name="power">    <option *ngFor="let pow of powers" [value]="pow">{{pow}}</option>  </select></div>

每个input元素都有id属性,label元素的for属性用它来匹配到对应的输入控件
每个input都有name属性,Angular表单用它来注册控件。

七、ngModel
在属性绑定中,值从模型中流动到屏幕的目标属性,通过把属性名括在方括号中来标记目标属性,[],这就是模型到视图的单向绑定。
在事件绑定中,值从屏幕上的目标流动到模型,通过属性名括在圆括号中来标记出目标属性,{}。这是从视图到模型的反向单向数据绑定。
Angular使用了[()]来标记出双向数据绑定和双向数据流。

八、通过ngModel跟踪修改状态与有效性验证
在表单中使用ngModel可以获得比双向数据绑定更多的控制权,他还会告诉我们很多信息:用户碰过此控件吗,他的值变化了吗,数据变得无效了吗。
ngModel指令不仅仅跟踪状态,他还使用特定的Angular css类来更新控件,以反映当前状态。

(1)控件是否被访问过
ng-touched
ng-untouched

(2)控件值是否已经变化
ng-dirty
ng-pristine

(3)控件值是否有效
ng-valid
ng-invalid

九、添加用于视觉反馈的自定义CSS
在新建的form.css文件中,添加两个样式来实现效果。

.ng-valid[required], .ng-valid.required  {  border-left: 5px solid #42A948; /* green */}.ng-invalid:not(form)  {  border-left: 5px solid #a94442; /* red */}

这些样式的作用于两个Angular有效性类和HTML5的required属性。
更新index.html中的head来包含这个样式表

<link rel="stylesheet" href="styles.css"><link rel="stylesheet" href="forms.css">

十、显示和隐藏验证错误信息
这里写图片描述
要达到这个效果,要在input标签中增加:
(1)模板引用变量
(2)is require消息,放在临近的div元素中,当控件无效时才显示他。

模板引用变量可以访问模板中输入框的Angular控件,这里,创建了名叫name的控件,并且赋值为ngModel。

为什么是ngModel?指令的exportAs属性告诉Angular如何链接模板引用变量到指令,这里把name设置为ngModel是因为ngModel指令的exports属性设置成了ngModel。

十一、添加英雄以及重置表单
再次运行应用,点击 New Hero 按钮,表单被清空了。 输入框左侧的必填项竖条是红色的,表示name和power属性是无效的。 这可以理解,因为有一些必填字段。 错误信息是隐藏的,因为表单还是全新的,还没有修改任何东西。

输入名字,再次点击 New Hero 按钮。 这次,出现了错误信息!为什么?我们不希望显示新(空)的英雄时,出现错误信息。

使用浏览器工具审查这个元素就会发现,这个 name 输入框并不是全新的。 表单记得我们在点击 New Hero 前输入的名字。 更换了英雄并不会重置控件的“全新”状态。

我们必须清除所有标记,在调用newHero()方法后调用表单的reset()方法即可。

十二、使用ngSubmit提交表单
在填表完成后,用户应该还能提交这个表单。Submit按钮位于表单底部,他自己不做任何事,但因为有特殊的type值(submit),所以会触发表单提交。
仅仅触发表单提交在目前是没有用的,要让他有用,还要用另外的Angular指令更新form标签–ngSubmit,并且通过事件绑定把他绑定到HeroFormComponent.submit方法中。

<form (ngSubmit)="onSubmit()" #heroForm="ngForm">

在这里定义了模板引用变量#heroForm,并初始化为ngForm。
Angular自动创建了NgForm指令,并附加到了form标签上,ngForm指令为form元素扩充了额外的特性,他持有通过ngModel指令和name属性为各个元素创建的各个控件,并且监听他们的属性变化,包括有效性,他还有自己的valid属性,只有当所有控件都有效时他才有效。

<button type="submit" class="btn btn-default" [disabled]="!heroForm.form.valid">Submit</button>
0 0
原创粉丝点击