标签(空格分隔): angular
首先阐述一下遇到的问题:
解决思路:
[abstractcontrol].root.get([targetname])
来取得指定的controller,然后比较他们的值。[target].seterrors([errors])
来实现。import {abstractcontrol, formgroup, validatorfn} from '@angular/forms'; import {g} from '../services/data-store.service'; export class myvalidators { private static isemptyinputvalue(value) { // we don't check for string here so it also works with arrays return value == null || value.length === 0; } private static isemptyobject(obj) { if (typeof obj === 'object' && typeof obj.length !== 'number') { return object.keys(obj).length === 0; } return null; } /** * 等于指定controller的值 * @param targetname 目标的formcontrolname * @returns {(ctrl: formcontrol) => {equalto: {valid: boolean}}} */ static equalto(targetname: string): validatorfn { return (control: abstractcontrol): {[key: string]: any} | null => { const target = control.root.get(targetname); if (target === null) { return null; } if (this.isemptyinputvalue(control.value)) { return null; } return target.value === control.value ? null : {'equalto': { valid: false }}; }; } /** * 反向输入监听指定controller是否与当前值相等 * @param targetname */ static equalfor(targetname: string): validatorfn { return (control: abstractcontrol): {[key: string]: any} | null => { const target = control.root.get(targetname); if (target === null) { return null; } if (this.isemptyinputvalue(control.value)) { return null; } if (target.value === control.value) { const errors = target.errors; delete errors['equalto']; if (this.isemptyobject(errors)) { target.seterrors(null); } else { target.seterrors(errors); } return null; } target.seterrors({ 'equalto': { valid: false } }); }; } ... }
(注:)其中g.regex
等的是全局变量。
formbuilder
来实现:import { component, oninit } from '@angular/core'; import {eventsservice} from '../../../services/events.service'; import {formbuilder, formgroup, validators} from '@angular/forms'; import {g} from '../../../services/data-store.service'; import {fade} from '../../../animations/fade.animation'; import {myvalidators} from '../../../directives/my-validators.directive'; @component({ selector: 'app-sign-up', templateurl: './sign-up.component.html', styleurls: ['./sign-up.component.scss'], animations: [fade] }) export class signupcomponent implements oninit { signform: formgroup; // 表单组formgroup submitting: boolean; // 是否可以提交 validations = g.validations; constructor(private eventsservice: eventsservice, private formbuilder: formbuilder) { this.submitting = false; // this.init(); } ngoninit() { // 设置父组件标题 this.eventsservice.publish('setsign', { title: '注册', subtitle: { name: '立即登录', uri: '/account/sign-in' } }); } // 立即注册 onsubmit() { console.log(this.signform.getrawvalue()); } // 表单初始化 private init() { this.signform = this.formbuilder.group({ username: ['', validators.compose([validators.required, validators.maxlength(this.validations.usr_max)])], password: ['', validators.compose([ validators.required, validators.minlength(this.validations.pass_min), validators.maxlength(this.validations.pass_max), myvalidators.equalfor('passwordconfirm') ])], passwordconfirm: ['', validators.compose([ validators.required, validators.minlength(this.validations.pass_min), validators.maxlength(this.validations.pass_max), myvalidators.equalto('password') ])] }); } }
(注:)其中fade
动画效果。
<form [formgroup]="signform" (ngsubmit)="onsubmit()" class="sign-form" @fade> <!-- 账号 --> <div class="input-group username"> <span class="addon prev"><i class="civ civ-i-usr"></i></span> <input type="text" name="username" class="form-control form-control-left default" placeholder="请输入账号" formcontrolname="username" autocomplete="off"> <ul class="errors" *ngif="signform.get('username').invalid && (signform.get('username').dirty || signform.get('username').touched)"> <li *ngif="signform.get('username').haserror('required')" class="error"> 请输入您的账号! </li> <li *ngif="signform.get('username').haserror('maxlength')" class="error"> 账号不超过{{ validations.usr_max }}位! </li> </ul> </div> <!-- /.账号 --> <!-- 密码 --> <div class="input-group password"> <span class="addon prev"><i class="civ civ-i-lock"></i></span> <input type="password" name="password" class="form-control form-control-left default" placeholder="请输入密码" formcontrolname="password"> <ul class="errors" *ngif="signform.get('password').invalid && (signform.get('password').dirty || signform.get('password').touched)"> <li *ngif="signform.get('password').haserror('required')" class="error"> 请输入您的密码! </li> <li *ngif="signform.get('password').haserror('minlength')" class="error"> 请输入至少{{ validations.pass_min }}位数的密码! </li> <li *ngif="signform.get('password').haserror('maxlength')" class="error"> 密码不超过{{ validations.pass_max }}位! </li> </ul> </div> <!-- /.密码 --> <!-- 重复密码 --> <div class="input-group password-confirm"> <span class="addon prev"><i class="civ civ-i-lock"></i></span> <input type="password" name="passwordconfirm" class="form-control form-control-left default" placeholder="请再次输入密码" formcontrolname="passwordconfirm"> <ul class="errors" *ngif="signform.get('passwordconfirm').invalid && (signform.get('passwordconfirm').dirty || signform.get('passwordconfirm').touched)"> <li *ngif="signform.get('passwordconfirm').haserror('required')" class="error"> 请再次输入密码! </li> <li *ngif="signform.get('passwordconfirm').haserror('minlength')" class="error"> 请输入至少{{ validations.pass_min }}位数的密码! </li> <li *ngif="signform.get('passwordconfirm').haserror('maxlength')" class="error"> 密码不超过{{ validations.pass_max }}位! </li> <li *ngif="!signform.get('passwordconfirm').haserror('maxlength') && !signform.get('passwordconfirm').haserror('minlength') && signform.get('passwordconfirm').haserror('equalto')" class="error"> 两次密码输入不一致! </li> </ul> </div> <!-- /.重复密码 --> <!-- 提交按钮 --> <button type="submit" class="btn btn-primary btn-block submit" [disabled]="submitting || signform.invalid">立即注册</button> <!-- /.提交按钮 --> </form>
最后,我们可以看到,实现了想要的效果:
(附:)完整的自定义表单验证器:
import {abstractcontrol, formgroup, validatorfn} from '@angular/forms'; import {g} from '../services/data-store.service'; export class myvalidators { private static isemptyinputvalue(value) { // we don't check for string here so it also works with arrays return value == null || value.length === 0; } private static isemptyobject(obj) { if (typeof obj === 'object' && typeof obj.length !== 'number') { return object.keys(obj).length === 0; } return null; } /** * 等于指定controller的值 * @param targetname 目标的formcontrolname * @returns {(ctrl: formcontrol) => {equalto: {valid: boolean}}} */ static equalto(targetname: string): validatorfn { return (control: abstractcontrol): {[key: string]: any} | null => { const target = control.root.get(targetname); if (target === null) { return null; } if (this.isemptyinputvalue(control.value)) { return null; } return target.value === control.value ? null : {'equalto': { valid: false }}; }; } /** * 反向输入监听指定controller是否与当前值相等 * @param targetname */ static equalfor(targetname: string): validatorfn { return (control: abstractcontrol): {[key: string]: any} | null => { const target = control.root.get(targetname); if (target === null) { return null; } if (this.isemptyinputvalue(control.value)) { return null; } if (target.value === control.value) { const errors = target.errors; delete errors['equalto']; if (this.isemptyobject(errors)) { target.seterrors(null); } else { target.seterrors(errors); } return null; } target.seterrors({ 'equalto': { valid: false } }); }; } /** * 验证手机号 * @returns {(ctrl: formcontrol) => {mobile: {valid: boolean}}} */ static get mobile() { return (control: abstractcontrol) => { if (this.isemptyinputvalue(control.value)) { return null; } const valid = g.regex.mobile.test(control.value); return valid ? null : { 'mobile': { valid: false } }; }; } /** * 验证身份证 * @returns {(ctrl: formcontrol) => {idcard: {valid: boolean}}} */ static get idcard() { return (control: abstractcontrol) => { if (this.isemptyinputvalue(control.value)) { return null; } const valid = g.regex.id_card.test(control.value); return valid ? null : { 'idcard': { valid: false } }; }; } /** * 验证汉字 * @returns {(ctrl: formcontrol) => {cn: {valid: boolean}}} */ static get cn() { return (control: abstractcontrol) => { if (this.isemptyinputvalue(control.value)) { return null; } const valid = g.regex.cn.test(control.value); return valid ? null : { 'cn': { valid: false } }; }; } /** * 指定个数数字 * @param {number} length * @returns {(ctrl: formcontrol) => (null | {number: {valid: boolean}})} */ static number(length: number = 6) { return (control: abstractcontrol) => { if (this.isemptyinputvalue(control.value)) { return null; } const valid = new regexp(`^\\d{${length}}$`).test(control.value); return valid ? null : { 'number': { valid: false } }; }; } /** * 强密码(必须包含数字字母) * @returns {(ctrl: formcontrol) => (null | {number: {valid: boolean}})} */ static get strictpass() { return (control: abstractcontrol) => { if (this.isemptyinputvalue(control.value)) { return null; } const valid = g.regex.strict_pass.test(control.value); return valid ? null : { 'strictpass': { valid: false } }; }; } }
如对本文有疑问, 点击进行留言回复!!
offset、client、scroll (width,height、left,top、X,Y)
网友评论