[英]password-check directive in angularjs
我正在写一个密码验证指令:
Directives.directive("passwordVerify",function(){
return {
require:"ngModel",
link: function(scope,element,attrs,ctrl){
ctrl.$parsers.unshift(function(viewValue){
var origin = scope.$eval(attrs["passwordVerify"]);
if(origin!==viewValue){
ctrl.$setValidity("passwordVerify",false);
return undefined;
}else{
ctrl.$setValidity("passwordVerify",true);
return viewValue;
}
});
}
};
});
HTML:
<input data-ng-model='user.password' type="password" name='password' placeholder='password' required>
<input data-ng-model='user.password_verify' type="password" name='confirm_password' placeholder='confirm password' required data-password-verify="user.password">
给定表单中的2个密码字段,如果两个密码值相等,则受该指令影响的字段有效。 问题是它以一种方式工作(即当我在密码验证字段中键入密码时)。 但是,更新原始密码字段时,密码验证不会生效。
知道如何进行“双向绑定验证”吗?
我使用以下指令,因为我想重新验证两个输入字段,无论值1还是值2都被更改:
指示:
'use strict';
angular.module('myApp').directive('equals', function() {
return {
restrict: 'A', // only activate on element attribute
require: '?ngModel', // get a hold of NgModelController
link: function(scope, elem, attrs, ngModel) {
if(!ngModel) return; // do nothing if no ng-model
// watch own value and re-validate on change
scope.$watch(attrs.ngModel, function() {
validate();
});
// observe the other value and re-validate on change
attrs.$observe('equals', function (val) {
validate();
});
var validate = function() {
// values
var val1 = ngModel.$viewValue;
var val2 = attrs.equals;
// set validity
ngModel.$setValidity('equals', ! val1 || ! val2 || val1 === val2);
};
}
}
});
用法
<input type="password" ng-model="value1" equals="{{value2}}" required>
<input type="password" ng-model="value2" equals="{{value1}}" required>
不需要为此创建单独的指令。 Angular UI密码验证工具已经内置了 。 有了这个,你可以这样做:
<input name="password" required ng-model="password">
<input name="confirm_password"
ui-validate=" '$value==password' "
ui-validate-watch=" 'password' ">
Passwords match? {{!!form.confirm_password.$error.validator}}
这应该解决它:
视图:
<div ng-controller='Ctrl'>
<form name='form'>
<input data-ng-model='user.password' type="password" name='password' placeholder='password' required>
<div ng-show="form.password.$error.required">
Field required</div>
<input ng-model='user.password_verify' type="password" name='confirm_password' placeholder='confirm password' required data-password-verify="user.password">
<div ng-show="form.confirm_password.$error.required">
Field required!</div>
<div ng-show="form.confirm_password.$error.passwordVerify">
Fields are not equal!</div>
</form
</div>
指示
var app = angular.module('myApp', []);
app.directive("passwordVerify", function() {
return {
require: "ngModel",
scope: {
passwordVerify: '='
},
link: function(scope, element, attrs, ctrl) {
scope.$watch(function() {
var combined;
if (scope.passwordVerify || ctrl.$viewValue) {
combined = scope.passwordVerify + '_' + ctrl.$viewValue;
}
return combined;
}, function(value) {
if (value) {
ctrl.$parsers.unshift(function(viewValue) {
var origin = scope.passwordVerify;
if (origin !== viewValue) {
ctrl.$setValidity("passwordVerify", false);
return undefined;
} else {
ctrl.$setValidity("passwordVerify", true);
return viewValue;
}
});
}
});
}
};
});
另一种观点是将一个输入的模型与另一个输入的值相匹配。
app.directive('nxEqual', function() {
return {
require: 'ngModel',
link: function (scope, elem, attrs, model) {
if (!attrs.nxEqual) {
console.error('nxEqual expects a model as an argument!');
return;
}
scope.$watch(attrs.nxEqual, function (value) {
model.$setValidity('nxEqual', value === model.$viewValue);
});
model.$parsers.push(function (value) {
var isValid = value === scope.$eval(attrs.nxEqual);
model.$setValidity('nxEqual', isValid);
return isValid ? value : undefined;
});
}
};
});
因此,如果密码框的模型是login.password
则在验证框中设置以下属性: nx-equal="login.password"
,并测试formName.elemName.$error.nxEqual
。 像这样:
<form name="form">
<input type="password" ng-model="login.password">
<input type="password" ng-model="login.verify" nx-equal="login.password" name="verify">
<span ng-show="form.verify.$error.nxEqual">Must be equal!</span>
</form>
扩大的视野:
对于我的一个新项目,我不得不修改上面的指令,这样只有当验证输入有一个值时才会显示nxEqual
错误。 否则应该静音nxEqual
错误。 这是扩展版本:
app.directive('nxEqualEx', function() {
return {
require: 'ngModel',
link: function (scope, elem, attrs, model) {
if (!attrs.nxEqualEx) {
console.error('nxEqualEx expects a model as an argument!');
return;
}
scope.$watch(attrs.nxEqualEx, function (value) {
// Only compare values if the second ctrl has a value.
if (model.$viewValue !== undefined && model.$viewValue !== '') {
model.$setValidity('nxEqualEx', value === model.$viewValue);
}
});
model.$parsers.push(function (value) {
// Mute the nxEqual error if the second ctrl is empty.
if (value === undefined || value === '') {
model.$setValidity('nxEqualEx', true);
return value;
}
var isValid = value === scope.$eval(attrs.nxEqualEx);
model.$setValidity('nxEqualEx', isValid);
return isValid ? value : undefined;
});
}
};
});
你会像这样使用它:
<form name="form">
<input type="password" ng-model="login.password">
<input type="password" ng-model="login.verify" nx-equal-ex="login.password" name="verify">
<span ng-show="form.verify.$error.nxEqualEx">Must be equal!</span>
</form>
试一试: http : //jsfiddle.net/gUSZS/
我没有指示就完成了。
<input type="password" ng-model="user.password" name="uPassword" required placeholder='Password' ng-minlength="3" ng-maxlength="15" title="3 to 15 characters" />
<span class="error" ng-show="form.uPassword.$dirty && form.uPassword.$error.minlength">Too short</span>
<span ng-show="form.uPassword.$dirty && form.uPassword.$error.required">Password required.</span><br />
<input type="password" ng-model="user.confirmpassword" name="ucPassword" required placeholder='Confirm Password' ng-minlength="3" ng-maxlength="15" title="3 to 15 characters" />
<span class="error" ng-show="form.ucPassword.$dirty && form.ucPassword.$error.minlength">Too short</span>
<span ng-show="form.ucPassword.$dirty && form.ucPassword.$error.required">Retype password.</span>
<div ng-show="(form.uPassword.$dirty && form.ucPassword.$dirty) && (user.password != user.confirmpassword)">
<span>Password mismatched</span>
</div>
从角度1.3.0-beta12开始,无效输入不会写入ngModel,因此您无法观看AND THEN验证,如您所见: http ://plnkr.co/edit/W6AFHF308nyKVMQ9vomw?p = preview。 引入了一个新的验证器管道,您可以附加到此以实现相同的功能。
实际上,在那个笔记上我已经为常见的额外验证器创建了一个bower组件: https : //github.com/intellix/angular-validators包括这个。
angular.module('validators').directive('equals', function() {
return {
restrict: 'A',
require: '?ngModel',
link: function(scope, elem, attrs, ngModel)
{
if (!ngModel) return;
attrs.$observe('equals', function() {
ngModel.$validate();
});
ngModel.$validators.equals = function(value) {
return value === attrs.equals;
};
}
};
});
angular.module('validators').directive('notEquals', function() {
return {
restrict: 'A',
require: '?ngModel',
link: function(scope, elem, attrs, ngModel)
{
if (!ngModel) return;
attrs.$observe('notEquals', function() {
ngModel.$validate();
});
ngModel.$validators.notEquals = function(value) {
return value === attrs.notEquals;
};
}
};
});
https://github.com/wongatech/angular-confirm-field是一个很好的项目。
这里的例子http://wongatech.github.io/angular-confirm-field/
下面的代码显示了具有已实现功能的2个输入字段
<input ng-confirm-field ng-model="emailconfirm" confirm-against="email" name="my-email-confirm"/>
<input ng-model="email" name="my-email" />
我之前成功使用过这个指令:
.directive('sameAs', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
ctrl.$parsers.unshift(function(viewValue) {
if (viewValue === scope[attrs.sameAs]) {
ctrl.$setValidity('sameAs', true);
return viewValue;
} else {
ctrl.$setValidity('sameAs', false);
return undefined;
}
});
}
};
});
<input ... name="password" />
<input type="password" placeholder="Confirm Password"
name="password2" ng-model="password2" ng-minlength="9" same-as='password' required>
我正在处理同样的问题,并发现了一篇关于Piotr Buda写的关于它的好博文 。 这是一个很好的阅读,它很好地解释了这个过程。 代码如下:
directives.directive("repeatPassword", function() {
return {
require: "ngModel",
link: function(scope, elem, attrs, ctrl) {
var otherInput = elem.inheritedData("$formController")[attrs.repeatPassword];
ctrl.$parsers.push(function(value) {
if(value === otherInput.$viewValue) {
ctrl.$setValidity("repeat", true);
return value;
}
ctrl.$setValidity("repeat", false);
});
otherInput.$parsers.push(function(value) {
ctrl.$setValidity("repeat", value === ctrl.$viewValue);
return value;
});
}
};
});
所以你可以这样做:
<input type="password" name="repeatPassword" id="repeatPassword" placeholder="repeat password" ng-model="user.repeatPassword" repeat-password="password" required>
归功于作者
这不够好:
<input type="password" ng-model="passwd1" />
<input type="password" ng-model="passwd2" />
<label ng-show="passwd1 != passwd2">Passwords do not match...</label>
<button ng-disabled="passwd1 != passwd2">Save</button>
简单,对我来说效果很好。
这个解决方案类似于Dominic Watson给出的解决方案,它使用$ validators并且是我最喜欢的解决方案。 唯一的变化是您可以观看表达。
$ validators模型值更改时应用的验证器集合。 对象中的键值是指验证器的名称,而函数是指验证操作。 验证操作以模型值作为参数提供,并且必须根据该验证的响应返回true或false值
来自https://code.angularjs.org/1.3.15/docs/api/ng/type/ngModel.NgModelController
我正在使用角度1.3。 我的指令看起来像这样
angular.module('app').directive("passwordConfirm", function() {
"use strict";
return {
require : "ngModel",
restrict : "A",
scope : {
//We will be checking that our input is equals to this expression
passwordConfirm : '&'
},
link : function(scope, element, attrs, ctrl) {
//The actual validation
function passwordConfirmValidator(modelValue, viewValue) {
return modelValue == scope.passwordConfirm();
}
//Register the validaton when this input changes
ctrl.$validators.passwordConfirm = passwordConfirmValidator;
//Also validate when the expression changes
scope.$watch(scope.passwordConfirm, ctrl.$validate);
}
};
});
使用它
<input type="password" ng-model="user.password"/>
<input type="password" ng-model="user.confirmPassword"
password-confirm="user.password" />
为了验证具有两个输入字段的表单,我找到了最合适的方式
app.directive('passwordVerify', function() {
return {
require: 'ngModel',
link: function (scope, elem, attrs, ctrl) {
if (!attrs.passwordVerify) {
return;
}
scope.$watch(attrs.passwordVerify, function (value) {
if( value === ctrl.$viewValue && value !== undefined) {
ctrl.$setValidity('passwordVerify', true);
ctrl.$setValidity("parse",undefined);
}
else {
ctrl.$setValidity('passwordVerify', false);
}
});
ctrl.$parsers.push(function (value) {
var isValid = value === scope.$eval(attrs.passwordVerify);
ctrl.$setValidity('passwordVerify', isValid);
return isValid ? value : undefined;
});
}
};
});
<div class="row">
<div class="col-md-10 col-md-offset-1">
<div class="form-group" ng-class="{ 'has-error': form.password.$dirty && form.password.$error.required || (form.password.$error.minlength || form.password.$error.maxlength)}">
<input type="password" name="password" ng-minlength="6" ng-maxlength="16" id="password" class="form-control" placeholder="Password" ng-model="user.password" required />
<span ng-show="form.password.$dirty && form.password.$error.required" class="help-block">Password is required</span>
<span ng-show="form.password.$error.minlength || form.password.$error.maxlength" class="help-block">Password must be 6-16 character long</span>
</div>
</div>
</div>
<div class="row">
<div class="col-md-10 col-md-offset-1">
<div class="form-group" ng-class="{ 'has-error': (form.confirm_password.$dirty && form.confirm_password.$error.required) || form.confirm_password.$error.passwordVerify }">
<input type="password" name="confirm_password" id="confirm_password" class="form-control" placeholder="Confirm Password" ng-model="user.confirm_password" required password-verify="user.password" />
<span ng-show="form.confirm_password.$dirty && form.confirm_password.$error.required" class="help-block">Confirm Password is required</span>
<span ng-show="form.confirm_password.$error.passwordVerify" class="help-block">Please make sure passwords match & must be 6-16 character long</span>
</div>
</div>
</div>
这有两种方式,简单而干净
JavaScript的
var app = angular.module("app");
app.controller("SamePaswordController", function () {
this.password;
this.confirm;
this.save = function () {
alert("Saved!");
};
}
app.directive("match", function () {
return {
restrict:"A",
require:"ngModel",
link: function(scope, element, attrs, ctrl) {
function matchValidator(value) {
scope.$watch(attrs.match, function(newValue, oldValue) {
var isValid = value === scope.$eval(attrs.match);
ctrl.$setValidity('match', isValid);
});
return value;
}
ctrl.$parsers.push(matchValidator);
}
};
});
HTML:记下匹配指令
<form name="regForm" ng-controller="SamePaswordController as regCtrl"
ng-submit="regForm.$valid && regCtrl.save()" novalidate>
<input name="password" ng-model="regCtrl.password"
type="password" required placeholder="Password"/>
<input name="confirm" ng-model="regCtrl.confirm" match="regCtrl.password"
type="password" required placeholder="Confirm password"/>
<div> regForm is valid:{{regForm.$valid}}</div>
<input type="submit" value="Save"/>
</form>
您可以使用此示例https://github.com/rogithub/roangularjs克隆repo
不是指令解决方案,但对我有用:
<input ng-model='user.password'
type="password"
name='password'
placeholder='password'
required>
<input ng-model='user.password_verify'
type="password"
name='confirm_password'
placeholder='confirm password'
ng-pattern="getPattern()"
required>
在控制器中:
//Escape the special chars
$scope.getPattern = function(){
return $scope.user.password &&
$scope.user.password.replace(/([.*+?^${}()|\[\]\/\\])/g, '\\$1');
}
以下是我对这个问题的看法。 该指令将与表单值而不是范围进行比较。
'use strict';
(function () {
angular.module('....').directive('equals', function ($timeout) {
return {
restrict: 'A',
require: ['^form', 'ngModel'],
scope: false,
link: function ($scope, elem, attrs, controllers) {
var validationKey = 'equals';
var form = controllers[0];
var ngModel = controllers[1];
if (!ngModel) {
return;
}
//run after view has rendered
$timeout(function(){
$scope.$watch(attrs.ngModel, validate);
$scope.$watch(form[attrs.equals], validate);
}, 0);
var validate = function () {
var value1 = ngModel.$viewValue;
var value2 = form[attrs.equals].$viewValue;
var validity = !value1 || !value2 || value1 === value2;
ngModel.$setValidity(validationKey, validity);
form[attrs.equals].$setValidity(validationKey,validity);
};
}
};
});
})();
在HTML中,现在引用的是实际形式而不是范围值:
<form name="myForm">
<input type="text" name="value1" equals="value2">
<input type="text" name="value2" equals="value1">
<div ng-show="myForm.$invalid">The form is invalid!</div>
</form>
为了在两个输入都发生变化时实现验证,我使用以下代码(这是其他所有答案的组合):
angular.module('app.directives')
.directive('passwordVerify', [function () {
return {
require: '?ngModel',
restrict: 'A',
scope: {
origin: '=passwordVerify'
},
link: function (scope, element, attrs, ctrl) {
if(!ctrl) {
return;
}
function validate(value) {
ctrl.$setValidity('passwordMatch', scope.origin === value);
return value;
}
ctrl.$parsers.unshift(validate);
scope.$watch('origin', function(value) {
validate(ctrl.$viewValue);
});
}
};
}]);
首先,我要感谢Fredric发布这个优秀的例子。 我巧合地遇到了一个小问题。 在你发布的小提琴http://jsfiddle.net/gUSZS/
如果您输入密码,然后在验证输入元素中输入相同的密码,一切正常,但尝试向第二个框添加空格,而角度将自动修剪该空间。 这意味着该指令不会“看到”额外的空间。 现在密码不同,但表单仍然有效。
为了解决这个问题,我们需要添加
ng-trim="false"
到输入元素。 这在角度1.0.3中不起作用,所以如果你想在这个小提琴中尝试它,你需要将1.1.1添加到小提琴( http://ajax.googleapis.com/ajax/libs/angularjs/1.1.1/angular .js )
但是,再次,弗雷德里克,我将在我的应用程序中使用您的解决方案!
安东PS我想评论弗雷德里克的帖子,但我是这个论坛的新手,似乎没有足够的信誉。 如果您喜欢,我们非常感谢你们中的一些人可以投票我的评论:-)
不需要额外的指令,这是我对此的看法:
HTML:
<div class="form-group" data-ng-class="{ 'has-error': submitted && !form.new_passwd.$valid }">
<input type="password" name="new_passwd" class="form-control" data-ng-model="data.new_passwd" placeholder="New Password" required data-ng-pattern="passwdRegex">
<small class="help-block" data-ng-show="submitted && form.new_passwd.$error.required">New password is required!</small>
<small class="help-block" data-ng-show="submitted && !form.new_passwd.$error.required && form.new_passwd.$error.pattern">New password is not strong enough!</small>
</div>
<div class="form-group" data-ng-class="{ 'has-error': submitted && !form.new_passwd_conf.$valid }">
<input type="password" name="new_passwd_conf" class="form-control" data-ng-model="data.new_passwd_conf" placeholder="Confirm New Password" required data-ng-pattern="passwdConfRegex">
<small class="help-block" data-ng-show="submitted && form.new_passwd_conf.$error.required">New password confirmation is required!</small>
<small class="help-block" data-ng-show="submitted && !form.new_passwd_conf.$error.required && form.new_passwd_conf.$error.pattern">New password confirmation does not match!</small>
</div>
使用Javascript:
$scope.passwdRegex = /^(?=.*[A-Z])(?=.*[a-z])(?=.*\d)(?=.*[^\da-zA-Z]).{8,}$/;
$scope.$watch('data.new_passwd', function() {
$scope.passwdConfRegex = new RegExp(Regex.escape($scope.data.new_passwd));
});
在这里可以找到Regex.escape()。
奇迹般有效!
要添加到大量现有解决方案中,这对我来说非常有用。
( Jan Laussmann回答停止使用最新的AngularJS beta版本)。
指示:
angular.module('myApp').directive('matchValidator', [function() {
return {
require: 'ngModel',
link: function(scope, elm, attr, ctrl) {
var pwdWidget = elm.inheritedData('$formController')[attr.matchValidator];
ctrl.$parsers.push(function(value) {
if (value === pwdWidget.$viewValue) {
ctrl.$setValidity('match', true);
return value;
}
if (value && pwdWidget.$viewValue) {
ctrl.$setValidity('match', false);
}
});
pwdWidget.$parsers.push(function(value) {
if (value && ctrl.$viewValue) {
ctrl.$setValidity('match', value === ctrl.$viewValue);
}
return value;
});
}
};
}])
用法
<input type="email" ng-model="value1" name="email" required>
<input type="email" ng-model="value2" name="emailConfirm" match-validator="email" required>
显示错误
<div ng-if="[[yourFormName]].emailConfirm.$error">
<div ng-if="[[yourFormName]].emailConfirm.$error.match">
Email addresses don't match.
</div>
</div>
<input name="password" type="text" required="" ng-model="password" placeholder="password" class="ng-dirty ng-valid ng-valid-required">
<input name="confirm_password" type="text" required="" ng-model="confirm_password" ui-validate=" '$value==password' " ui-validate-watch=" 'password' " placeholder="confirm password" class="ng-dirty ng-valid-required ng-invalid ng-invalid-validator">
<span ng-show="form.confirm_password.$error.validator">Passwords do not match!</span>
password errors: {
"required": false,
"validator": true
}
这对我有用。
指示:
modulename.directive('passwordCheck', function () {
return {
restrict: 'A', // only activate on element attribute
require: '?ngModel', // get a hold of NgModelController
link: function (scope, elem, attrs, ngModel) {
if (!ngModel) return; // do nothing if no ng-model
var Value = null;
// watch own value and re-validate on change
scope.$watch(attrs.ngModel, function (val) {
Value = val;
validate();
});
// observe the other value and re-validate on change
attrs.$observe('passwordCheck', function () {
validate();
});
var validate = function () {
// values
var val1 = Value;
var val2 = attrs.passwordCheck;
// set validity
if (val1 != '' && val1 != undefined) {
ngModel.$setValidity('passwordCheck', val1 == val2);
}
else {
ngModel.$setValidity('passwordCheck', true);
}
};
}
}
});
HTML:
ng-model="confirmpassword.selected" type="password" name="confirmpassword"
password-check="{{password.selected}}"
ng-show="resetpasswordform.confirmpassword.$error.passwordCheck && submitted" Password does not match
当我试图建立我自己的指令时,我遇到了同样的问题,我修复了这个添加
ctrl.$validate();
其中ctrl是我的ngModelController
这是我的看法
<input type="password" match="signupCtrl.registrationData.password" name="confirmPassword" class="form-control" placeholder="Confirm Password" data-ng-model="signupCtrl.registrationData.confirmPassword" required>
<span ng-messages="registerForm.confirmPassword.$error">
<span ng-message="match">The Password must match</span>
</span>
这是我的指示
(function () {
'use strict';
angular.module('matchDirective', [
// Angular modules
// Custom modules
// 3rd Party Modules
]);
})();
(function () {
'use strict';
angular
.module('matchDirective')
.directive('match', match);
match.$inject = ['$window'];
function match($window) {
// Usage:
// <element match="source"></element>
// Creates:
//
var directive = {
link: link,
restrict: 'A',
require: 'ngModel',
};
return directive;
function link(scope, element, attrs, ctrl) {
scope.$watch(attrs['match'], function (newVal, oldVal) {
ctrl.$validators.match = function (modelValue, viewValue) {
if (newVal == modelValue) {
return true;
} else {
return false;
}
}
ctrl.$validate();
});
}
}
})();
这样的东西适合我:
JS:
.directive('sameAs', function() { return {
require : 'ngModel',
link : function(scope, elm, attrs, ngModelCtrl) {
ngModelCtrl.$validators.sameAs = function(modelValue, viewValue) {
var checkedVal = attrs.sameAs;
var thisInputVal = viewValue;
if (thisInputVal == checkedVal) {
return true; // valid
} else {
return false;
}
};
}
}; });
HTML:
<input type="password" name="password" id="password" ng-model="password" />
<input type="password" name="passwordRepeat" id="passwordRepeat"
ng-model="passwordRepeat" same-as="{{password}}" />
保持简单和愚蠢(KISS)原则可能对此有用。 通过执行以下操作,更快速,更轻松地检查两个密码是否匹配:
<div ng-app="app" ng-controller="passwordCheck">
<form name="signUp" ng-submit="submitForm()" novalidate>
<input type="password" name="password" ng-model="password" required>
<input type="password" name="ConfirmPassword" ng-model="passwordconfirm" required>
<button type="submit"> Submit</button>
</form>
<hr>
<span>Do they match?</span> {{signUp.password.$viewValue == signUp.confirmPassword.$viewValue}}
</div>
在提交表单之前,您可以在js中执行此操作
var app = angular.module("app", []);
app.controller("passwordCheck", function($scope) {
$scope.submitForm = function() {
if ($scope.signUp.$valid && $scope.signUp.password.$viewValue == $scope.signUp.confirmPassword.$viewValue) {
alert('Its a match!');
};
};
});
你也可以在JSfiddle中测试它。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.