今天我们继续学习angular4表单的内容,表单是系统中都不可或缺的一部分,所以在angular中提供了表单模块,表单的内容分为以下几个部分:
- 模板表单
- 模板表单的验证
- 响应式表单
- 响应式表单的验证
所以我们也是通过一个小的Demo来一步步完成这四部分的学习。
(一)准备工作
新建一个项目 ng new angular-form-demo
(二)模板表单
首先先新建一个组件 ng g component form/template-form
然后先按照我们原始的方式写出表单
代码如下:
<
form
action=
""
>
< div > 用户名: < input type= "text" name= "username" /></ div >
< div > 密码: < input type= "text" name= "password" /></ div >
< div > 确认密码: < input type= "text" name= "confirmpass" /></ div >
< div > 电话: < input type= "text" name= "mobile" /></ div >
< div >< input type= "submit" value= " 提交 " /></ div >
< div > 用户名: < input type= "text" name= "username" /></ div >
< div > 密码: < input type= "text" name= "password" /></ div >
< div > 确认密码: < input type= "text" name= "confirmpass" /></ div >
< div > 电话: < input type= "text" name= "mobile" /></ div >
< div >< input type= "submit" value= " 提交 " /></ div >
</form>
angular中定义了一些指令使用在表单上,要想在后台中获取表单字段,我们必须用特定的指令去标明,如下面是使用ng template-form之后的表单.
<
form
#myForm =
"ngForm"
(ngSubmit) =
"
onSubmit
(
myForm
.value)"
>
< div > 用户名: < input ngModel type= "text" name= "username" /></ div >
< div ngModelGroup= "passwordGroup" >
< div > 密码: < input ngModel type= "password" name= "password" /></ div >
< div > 确认密码: < input ngModel type= "password" name= "confirmPass" /></ div >
</ div >
< div > 电话: < input ngModel type= "text" name= "mobile" /></ div >
< div >< input type= "submit" value= " 提交 " /></ div >
< div > 用户名: < input ngModel type= "text" name= "username" /></ div >
< div ngModelGroup= "passwordGroup" >
< div > 密码: < input ngModel type= "password" name= "password" /></ div >
< div > 确认密码: < input ngModel type= "password" name= "confirmPass" /></ div >
</ div >
< div > 电话: < input ngModel type= "text" name= "mobile" /></ div >
< div >< input type= "submit" value= " 提交 " /></ div >
</form>
Notice: you should import the FormModules in config files if you have an error like below:
#myForm是模板变量,myForm变量可以自定义,但是如果是表单文件,#myForm后面的值 'ngForm'是固定的。
'template-form.component.ts ' you can receive the data from front end in here,
onSubmit(value) {
console. log(value);
console. log(value);
}
the result:
(三)模板表单的验证
在表单中,有些字段是必填项,有些字段长度有限制,又有些字段要求符合某个特定的规则(比如密码和确认密码框要相同),针对上述经常出现的现象,我们分别来讲如何在angular中实现:
①必填项
在字段中添加required属性即可,如果表单为空,还需要出现提示信息,实现方式如下:
<
div
class=
"form-control"
>
< label for= "username" > 用户名: </ label >
< input [(ngModel)] = " model . name " type= "text" name= "username" id= "username" required #uname= "ngModel" />
< div [hidden] = ' uname . valid || uname . pristine ' >
userName is required!
</ div >
< label for= "username" > 用户名: </ label >
< input [(ngModel)] = " model . name " type= "text" name= "username" id= "username" required #uname= "ngModel" />
< div [hidden] = ' uname . valid || uname . pristine ' >
userName is required!
</ div >
</div>
在上面的代码中uname是一个模板变量,把他绑定到ngModel上,这样该input的所有className状态都会被angular添加上。下面附上angular css的状态码信息:
上面Hidden的字段表示字典有效或者字段值没有变化时隐藏改提示,毕竟我们也想提供好的用户体验嘛。
除了上一种方式,我们也可以使用*ngIf指令来实现上述效果,代码如下所示:
<
div
class=
"form-control"
>
< label for= "username" > 用户名: </ label >
< input [(ngModel)] = " model . name " type= "text" name= "username" id= "username" required #uname= "ngModel" />
< div *ngIf= " uname . invalid && ( uname . touched || uname . dirty )" >
< div *ngIf= " uname .errors. required " >
username is required yet.
</ div >
</ div >
< label for= "username" > 用户名: </ label >
< input [(ngModel)] = " model . name " type= "text" name= "username" id= "username" required #uname= "ngModel" />
< div *ngIf= " uname . invalid && ( uname . touched || uname . dirty )" >
< div *ngIf= " uname .errors. required " >
username is required yet.
</ div >
</ div >
</div>
还有另外一种方式如下,这种方式不用把每个字段绑定到ngModel上:
<
div
class=
"form-control"
>
<label for="username">用户名:</label>
<input ngModel type="text" name="username" id="username" required/>
<
div
[hidden] =
"!
myForm
.
form
.
hasError
('required','username')"
>
userName is required!
</ div >
</ div >
userName is required!
</ div >
</ div >
②长度限制
比如密码的长度要限制为至少6个字符时,我们需要在angular中按照如下的方式实现:
<
div
>
< label for= "password" > 密码: </ label >
< input ngModel type= "password" name= "password" id= "password" required minlength= "6" #pass= "ngModel" />
< div *ngIf= " pass . invalid && ( pass . touched || pass . dirty )" >
< div *ngIf= " pass .errors. minlength " >
password must be at least 6 character long
</ div >
</ div >
< label for= "password" > 密码: </ label >
< input ngModel type= "password" name= "password" id= "password" required minlength= "6" #pass= "ngModel" />
< div *ngIf= " pass . invalid && ( pass . touched || pass . dirty )" >
< div *ngIf= " pass .errors. minlength " >
password must be at least 6 character long
</ div >
</ div >
</div>
上述实现方式也是结合angular指令来实现的,比如先定义属性minlength = "6",然后进行验证。最大长度也是同样的方法实现。
③自定义规则,比如验证电话号码是否符合规则,或者密码和确认密码是否相同。这些可以利用angular中自定义指令来实现,下面我们就以两个密码相同为例,来看看是如何实现的。
首先我们先自定义一个验证组件 validators.ts ,这里面存放一些通用的验证规则。下面是判断密码相等的验证方法。
export function
equalValidator(group: FormGroup):
any {
let password: FormControl = group. get( "password") as FormControl;
let cPassword:FormControl = group. get( "confirmPass") as FormControl;
let valid = ( password. value === cPassword. value);
return valid ? null :{ "equal": true};
let password: FormControl = group. get( "password") as FormControl;
let cPassword:FormControl = group. get( "confirmPass") as FormControl;
let valid = ( password. value === cPassword. value);
return valid ? null :{ "equal": true};
}
然后我们再新建一个判断相等的指令,这样就可以在模板中使用它了. ng g directive directives/equalsValidator
指令和组件的区别就是指令没有模板,selector用[directorName]括起来,这意味着指令是可以用在html属性中的,然后再配置一个providers的提供
器,校验器的provide值固定为NG_VALIDATORS,useValue为刚才定义的验证方法名。
import { Directive }
from
'@angular/core';
import { NG_VALIDATORS } from '@angular/forms';
import { equalValidator} from "../validator/validators";
@Directive({
selector: '[equal]',
providers :[{
provide : NG_VALIDATORS,
useValue : equalValidator,
multi: true
}],
})
export class EqualValidatorDirective {
constructor() { }
}
import { NG_VALIDATORS } from '@angular/forms';
import { equalValidator} from "../validator/validators";
@Directive({
selector: '[equal]',
providers :[{
provide : NG_VALIDATORS,
useValue : equalValidator,
multi: true
}],
})
export class EqualValidatorDirective {
constructor() { }
}
最后我们在模板中像用正常指令一样写入刚才自定义的指令,这样就可以实现验证两个密码是否相等的需求了,同理,我们还可以自定义验证手机号码是否符合规范。详细信息请移步gitHub上去看,你也可以下载我写好的demo :
https://github.com/Dan2Lin/angular-form-demo.git
<
div
class=
"form-control"
ngModelGroup=
"passwordGroup"
equal
>
< div >
< label for= "password" > 密码: </ label >
< input ngModel type= "password" name= "password" id= "password" required minlength= "6" #pass= "ngModel" />
< div *ngIf= " pass . invalid && ( pass . touched || pass . dirty )" >
< div *ngIf= " pass .errors. minlength " >
password must be at least 6 character long
</ div >
</ div >
</ div >
< div >
< label for= "confirmPass" > 确认密码: </ label >
< input ngModel type= "password" name= "confirmPass" id= "confirmPass" required />
</ div >
< div [hidden] = "! myForm.form.hasError ('equal','passwordGroup')" >
两次密码不一致!
</ div >
< div >
< label for= "password" > 密码: </ label >
< input ngModel type= "password" name= "password" id= "password" required minlength= "6" #pass= "ngModel" />
< div *ngIf= " pass . invalid && ( pass . touched || pass . dirty )" >
< div *ngIf= " pass .errors. minlength " >
password must be at least 6 character long
</ div >
</ div >
</ div >
< div >
< label for= "confirmPass" > 确认密码: </ label >
< input ngModel type= "password" name= "confirmPass" id= "confirmPass" required />
</ div >
< div [hidden] = "! myForm.form.hasError ('equal','passwordGroup')" >
两次密码不一致!
</ div >
</div>
ok,到这里我们就学完了angular4中表单的第一部分,模板式表单以及验证,模板式表单一般用在简单表单,如果表单的规则比较多,通常会选择响应式表单,下次我们将继续学习表单的第二部分。