今天我们继续学习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中表单的第一部分,模板式表单以及验证,模板式表单一般用在简单表单,如果表单的规则比较多,通常会选择响应式表单,下次我们将继续学习表单的第二部分。