Monday, May 20, 2024
 Popular · Latest · Hot · Upcoming
121
rated 0 times [  126] [ 5]  / answers: 1 / hits: 5602  / 11 Years ago, wed, january 29, 2014, 12:00:00

I've written a match-model Angular directive that I use for password/password-repeat process when users register in my application. Password repeat field has this particular attribute that validates this field against original password field.



My directive has scope.$watch for optimization purposes because I don't have to read related scope property value each time I validate my repeat password scope property but I rather just use cached value which changes when related scope property value changes (original password).



This is my directive:



.directive(matchModel, [$timeout, function ($timeout) {
return {
require: ngModel,
link: function (scope, element, attributes, ngModelController) {

var valueCache = null;

// watch match-model model property value
scope.$watch(attributes[matchModel], function (newValue, oldValue) {
valueCache = newValue;
/*
scope.$apply(); // error $digest in progress
$timeout(function () { scope.$digest(); }); // no error, not working
$timeout(function () { scope.$apply(); }); // no error, not working
*/
});

// add model validation parser
ngModelController.$parsers.unshift(function (value) {
ngModelController.$setValidity(match, value === valueCache);
return value === valueCache ? value : undefined;
});
}
};
}]);


My form consists of two fields (that are relevant for this question):



<input type=password name=password id=password placeholder=password
class=validate autocomplete=off
required
ng-minlength=6
ng-model=data.password />
<input type=password name=passwordRepeat id=passwordRepeat placeholder=repeat password
class=validate autocomplete=off
required
ng-model=data.passwordRepeat
match-model=data.password />


Requirements




  1. When user enters first password, field becomes valid when enough characters are entered - in above case that's 6 characters

  2. when user enters second password, field should become valid when data matches first password

  3. if user returns to first field and changes original password, second field should invalidate



How it currently works



1 and 2 work as expected, but 3 doesn't. That's why I wanted to add scope.$digest to propagate scope model changes to other fields. And scope.$watch is the right moment because it executes when that particular scope model property changes.



It seems that scope.$digest (or scope.$apply for that matter) doesn't validate model. Validation doesn't seem to be executed along with it.



Question



So how should I do something like scope.$validate or even better element.$validate so it would only validate my particular field instead of the whole model (resulting in invalid form in the UI).


More From » angularjs

 Answers
3

I would do it by explicitly validating the $viewValue inside the $watch:



PLUNKER



app.directive(matchModel, [
function () {
return {
require: ngModel,
link: function (scope, element, attributes, ngModelController) {

var valueCache = null;

scope.$watch(attributes[matchModel], function (newValue, oldValue) {
valueCache = newValue;
validate(ngModelController.$viewValue);
});

var validate = function (value) {
ngModelController.$setValidity(match, value === valueCache);
return value === valueCache ? value : undefined;
};

ngModelController.$parsers.unshift(validate);
}
};
}]);

[#48249] Tuesday, January 28, 2014, 11 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
mireyag

Total Points: 73
Total Questions: 107
Total Answers: 85

Location: Ukraine
Member since Sun, Dec 13, 2020
4 Years ago
;