目录

一:校验表单的使用

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):表单的更多相关文章

  1. BootStrap 智能表单系列 六 表单数据绑定(编辑页面的数据绑定)

    本章介绍如何在生成表单后,将一个model的数据展示到form表单中(一般用于编辑页面) 代码如下(连接地址:https://github.com/xiexingen/Bootstrap-SmartF ...

  2. BootStrap 智能表单系列 五 表单依赖插件处理

    这一章比较简单哦,主要就是生产表单元素后的一些后续处理操作,比如日期插件的渲染.一些autocomplete的处理等,在回调里面处理就可以了, demo: $("input.date-pic ...

  3. BootStrap 智能表单系列 四 表单布局介绍

    表单的布局分为自动布局和自定义布局两种: 自动布局就是根据配置项中第二级配置项中数组的长度来自动使用不同的bootstrap栅格,通过设置autoLayout为true可以实现自动布局 自动以布局就是 ...

  4. 【SqlServer系列】表单查询

    1   概述 如下几个问题,如果你能解决,请继续往下看,若不能解决,请先复习SQL基础知识,再来阅读本篇文章.本篇文章深度中等左右. Q1:表StudentScores如下,用一条SQL语句查询出每门 ...

  5. 04. Web大前端时代之:HTML5+CSS3入门系列~HTML5 表单

    Web大前端时代之:HTML5+CSS3入门系列:http://www.cnblogs.com/dunitian/p/5121725.html 一.input新增类型: 1.tel:输入类型用于应该包 ...

  6. SpringMVC学习系列 之 表单标签

    http://www.cnblogs.com/liukemng/p/3754211.html 本篇我们来学习Spring MVC表单标签的使用,借助于Spring MVC提供的表单标签可以让我们在视图 ...

  7. BootStrap 智能表单系列 八 表单配置json详解

    本章属于该系列的高级部分,将介绍表单中一些列的配置 1.config列的配置: 主要用于控制布局 :config:{autoLayout:true|'1,2,2,4'} true:根据配置项最里层的数 ...

  8. AnjularJS系列2 —— 表单控件功能相关指令

    第二篇,表单控件功能相关指令. ng-checked控制radio和checkbox的选中状态 ng-selected控制下拉框的选中状态 ng-disabled控制失效状态 ng-multiple控 ...

  9. JS组件系列——Form表单验证神器: BootstrapValidator

    前言:做Web开发的我们,表单验证是再常见不过的需求了.友好的错误提示能增加用户体验.博主搜索bootstrap表单验证,搜到的结果大部分都是文中的主题:bootstrapvalidator.今天就来 ...

随机推荐

  1. python中的模块,以及包的导入的总结

    模块导入的方式: 模块的概念:一个.py文件就称为一个模块 导入模块中函数的方式: 方式一:import  模块名 使用时:模块名.函数名() 方式二 :from 模块名 import  函数名 使用 ...

  2. Docker 中的一些概念

    笔者使用 Mac 系统玩的,所以会更多阐述 Mac 上使用的一些东西. 在安装之前有些 Docker 相关的概念需要了解一下,以便我们更好了解 Docker. 简单来说,安装 Docker 之后,会在 ...

  3. Mybatis源码解析-MapperRegistry注册mapper接口

    知识储备 SqlsessionFactory-mybatis持久层操作数据的根本,具体的解析是通过SqlSessionFactoryBean生成的,具体的形成可见>>>Spring ...

  4. 【Mysql】复制表结构+数据(转)

    1:复制表结构及数据到新表 select * into 目的数据库名.dbo.目的表名 from 原表名 select * into my0735home.dbo.infoMianTest from ...

  5. es6 解构赋值

    ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring). 关于给变量赋值,传统的变量赋值是这样的: var arr = [1,2,3];//把数组的值 ...

  6. Java 9 揭秘(20. JDK 9中API层次的改变)

    Tips 做一个终身学习的人. 在最后一章内容中,主要介绍以下内容: 下划线作为新关键字 改进使用try-with-resources块的语法 如何在匿名类中使用<>操作符 如何在接口中使 ...

  7. Azure 认知服务 (4) 计算机视觉API - 读取图片中的文字 (OCR)

    <Windows Azure Platform 系列文章目录> 微软Azure认知服务的计算机视觉API,还提供读取图片中的文字功能 在海外的Windows Azure认知服务的读取图片功 ...

  8. Vivado完成综合_实现_生成比特流后发出提醒声音-原创☺

    之前做技术支持时,有过客户吐槽Vivado运行时间长,又不能在完成工作后发送提醒,这两天又有人提起,所以决定写篇帖子. 大家知道,Vivado的技术文档总提及tcl,不过似乎很不招人待见,很少有人研究 ...

  9. App 组件化/模块化之路——Android 框架组件(Android Architecture Components)使用指南

    面对越来越复杂的 App 需求,Google 官方发布了Android 框架组件库(Android Architecture Components ).为开发者更好的开发 App 提供了非常好的样本. ...

  10. 23. leetcode 169. Majority Element

    169. Majority Element Given an array of size n, find the majority element. The majority element is t ...