迈向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.今天就来 ...
随机推荐
- 基于android的语音质量评估
最近研究如何通过android评估通话质量,希望获取的参数有:(1)接通时长 (2)掉话次数 (3)语音是否清晰,以下将给出接通时长和掉话次数的详细定义: 接通时长:通话一方开始拨号到另一方开始振铃的 ...
- iOS开发实战-时光记账Demo 本地数据库版
现在记账APP也是用途比较广泛 自己写了个简单的demo 欢迎指正 效果 分析 1.思维推导 首先简单的做了下思维推导 2.文件结构 大致框架想好后就可以着手开始准备了 数据库管理:coreData ...
- ORACLE - 系统参数调整
一.内存调整 oracle 11g中,ORACLE把SGA与PGA统一管理,总和为memory_target参数的设定,也就是MAX(SGA+PGA)<= memory_target(当然可以在 ...
- 31. leetcode 122. Best Time to Buy and Sell Stock II
122. Best Time to Buy and Sell Stock II Say you have an array for which the ith element is the price ...
- 时间戳,取值问题 and 倒计时的前端处理
JavaScript 获取当前时间戳: 第一种方法: var timestamp = Date.parse(new Date()); 获取的时间戳是把毫秒改成000显示, 结果:12809773300 ...
- mybatis 详解(四)------properties以及别名定义
上一篇博客我们介绍了mybatis的增删改查入门实例,我们发现在 mybatis-configuration.xml 的配置文件中,对数据库的配置都是硬编码在这个xml文件中,如下图,那么我们如何改进 ...
- Shell排序
public void shellSort(int[] array) { int increment = array.length; do { increment = increment / 2; / ...
- hdu--1258--Sum It Up(Map水过)
Sum It Up Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total S ...
- MySQL checkpoint深入分析
1.日常关注点的问题 2.日志点分析 3.checkpoint:脏页刷盘的检查点 4.模糊检查点发生条件 1.master thread checkpoint 2.flush_lru_list che ...
- 【python密码学编程】7.暴力破解凯撒加密法
# _*_ coding:utf-8 _*_ #Caeser Ciper import pyperclip messgae = 'GUVF VF ZL FRPERG ZRFFTNR.' nums = ...