迈向angularjs2系列(7):表单
目录
一:校验表单的使用
1.搭建脚手架
2.校验表单的使用
3.select下拉列表的用法
一: 校验表单的使用
对于CRUD型的应用,表单是必备组件。

1.搭建脚手架
git clone https://github.com/mgechev/switching-to-angular2.git form1
npm install
npm start
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);
email自定义校验
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>
index.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,也就不会有再次提交了。妙!
迈向angularjs2系列(7):表单的更多相关文章
- BootStrap 智能表单系列 六 表单数据绑定(编辑页面的数据绑定)
本章介绍如何在生成表单后,将一个model的数据展示到form表单中(一般用于编辑页面) 代码如下(连接地址:https://github.com/xiexingen/Bootstrap-SmartF ...
- BootStrap 智能表单系列 五 表单依赖插件处理
这一章比较简单哦,主要就是生产表单元素后的一些后续处理操作,比如日期插件的渲染.一些autocomplete的处理等,在回调里面处理就可以了, demo: $("input.date-pic ...
- BootStrap 智能表单系列 四 表单布局介绍
表单的布局分为自动布局和自定义布局两种: 自动布局就是根据配置项中第二级配置项中数组的长度来自动使用不同的bootstrap栅格,通过设置autoLayout为true可以实现自动布局 自动以布局就是 ...
- 【SqlServer系列】表单查询
1 概述 如下几个问题,如果你能解决,请继续往下看,若不能解决,请先复习SQL基础知识,再来阅读本篇文章.本篇文章深度中等左右. Q1:表StudentScores如下,用一条SQL语句查询出每门 ...
- 04. Web大前端时代之:HTML5+CSS3入门系列~HTML5 表单
Web大前端时代之:HTML5+CSS3入门系列:http://www.cnblogs.com/dunitian/p/5121725.html 一.input新增类型: 1.tel:输入类型用于应该包 ...
- SpringMVC学习系列 之 表单标签
http://www.cnblogs.com/liukemng/p/3754211.html 本篇我们来学习Spring MVC表单标签的使用,借助于Spring MVC提供的表单标签可以让我们在视图 ...
- BootStrap 智能表单系列 八 表单配置json详解
本章属于该系列的高级部分,将介绍表单中一些列的配置 1.config列的配置: 主要用于控制布局 :config:{autoLayout:true|'1,2,2,4'} true:根据配置项最里层的数 ...
- AnjularJS系列2 —— 表单控件功能相关指令
第二篇,表单控件功能相关指令. ng-checked控制radio和checkbox的选中状态 ng-selected控制下拉框的选中状态 ng-disabled控制失效状态 ng-multiple控 ...
- JS组件系列——Form表单验证神器: BootstrapValidator
前言:做Web开发的我们,表单验证是再常见不过的需求了.友好的错误提示能增加用户体验.博主搜索bootstrap表单验证,搜到的结果大部分都是文中的主题:bootstrapvalidator.今天就来 ...
随机推荐
- 用Collections.synchronizedCollection创建线程安全的集合、列表。。。
Collection c=Collections.synchronizedCollection(new ArrayList()); List list=Collections.synchronized ...
- IDEA+Java:Selenium+Maven+TestNG基本WebUI自动化测试环境搭建
IDEA+java:Selenium+Maven+TestNG 本文介绍的测试环境,应该是最基本的测试环境了,也是很多文章都有写,这里做一个完整的图文配置整理,方便阅读理解! 使用maven的好处,由 ...
- CloseHandle 函数--关闭一个句柄
CloseHandle函数 来源:https://msdn.microsoft.com/en-us/library/windows/desktop/ms724211(v=vs.85).aspx 作用 ...
- 【TRICK】解决锚点定位向下浮动Xpx问题
1. 问题描述 页面滚动后,菜单栏会固定在页头,当锚点定位时,菜单会遮盖部分定位后的内容,所以需要在锚点定位后自动向下漂移Xpx. 2. 解决办法 a. 利用空div 占位,如下: <a hre ...
- linux任务前后台执行
Linux任务前后台的切换 Shell支持作用控制,有以下命令实现前后台切换: 1. command& 让进程在后台运行 2. jobs 查看后台运行的进程 3. fg %n 让后台运行的进程 ...
- ABP从入门到精通(3):aspnet-zero-core 使用Redis缓存
一.Redis是什么? redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset ...
- LoadRunner性能测试-LoadRunner工具安装
Loadrunner11安装 1,在网上下载loadrunner11安装包 (百度可以下载安装包) 2,打开安装文件,点击setup.exe进行安装: 3,win10系统可能会出现如下问题: 提示管理 ...
- 双向循环链表(C语言描述)(三)
代码清单 // linkedlist.h #ifndef __LINKEDLIST_H__ #define __LINKEDLIST_H__ #include <assert.h> #in ...
- CgLib动态代理学习【Spring AOP基础之一】
如果不了解JDK中proxy动态代理机制的可以先查看上篇文章的内容:Java动态代理学习[Spring AOP基础之一] 由于Java动态代理Proxy.newProxyInstance()的时候会发 ...
- 社交系统ThinkSNS+ 发布通知!
社交系统ThinkSNS 最新版本ThinkSNS+将于7月15日正式发布开源版本web+H5,同时发布Android APP和iOS APP.我们将告别内测阶段,正式对外发布. 没错,你们没看错,就 ...