Reputation: 9820
I have a directive I have created to validate password strength.
/**
*
* A directive that compares the model value of the associated input
* against an algorythm to prevent poor passwords.
*
* Passwords must contain the following.
* at least one uppercase letter
* at least one lowercase letter
* at least one numeric character
* at least one special character
* No more than 2 sequential alpha characters
* No more than 2 sequential numeric characters
* No more than 2 consecutive alpha characters
* No consecutive numeric characters
* No consecutive symbols
*
*/
app.directive('passwordStrength',[function()
{
return {
restrict: "A",
require: 'ngModel',
link: function($scope, $element, $attrs, ctrl)
{
if(!ctrl) return;
// Observe when a change is made to the comparitor value
$attrs.$observe('passwordStrength', function(value)
{
ctrl.$validate();
});
//
ctrl.$validators.passwordStrength = function(modelValue, viewValue)
{
// Strings to use to validate against sequentials.
// and accepted special characters.
var sAlphas = "abcdefghijklmnopqrstuvwxyz";
var sNumerics = "0123456789";
var sSymbols = '?!@#$%^&*(){}[]<>';
var sFwd = "";
var sRev = "";
var alphaFail = false;
var numericFail = false;
var alphaConsecFail = false;
var numericConsecFail = false;
var symbolConsecFail = false;
console.log($element.value);
// Fail if the password doesn't contain at leasto one uppercase letter
if(!modelValue.match(/[A-Z]/))
{
ctrl.$setValidity('alphaUpper', false);
console.log("Failed uppercase character check");
return false;
}
// Fail if the password doesn't contain at leasto one lowercase letter
if(modelValue.match(/[a-z]/))
{
ctrl.$setValidity('alphaLower', false);
console.log("Failed lowercase character check");
return false;
}
// Fail if the password doesn't contain at least one number
if(modelValue.match(/[0-9]/))
{
ctrl.$setValidity('numeric', false);
console.log("Failed numeric character check");
return false;
}
// Make sure that there are no sequential letters of 3 or more.
for (var s=0; s < 23; s++)
{
sFwd = sAlphas.substring(s,parseInt(s+3)).toLowerCase();
sRev = sFwd.strReverse();
if(
(modelValue.indexOf(sFwd) != -1 && modelValue != "") ||
(modelValue.indexOf(sRev) != -1 && modelValue != "")
)
{
alphaFail = true;
}
}
if(alphaFail)
{
console.log("Failed sequential alpha character check");
ctrl.$setValidity('serialAlpha', false);
return false;
}
// Make sure that there are no sequential letters of 3 or more.
var numericFail = false;
for (var s=0; s < 8; s++)
{
sFwd = sNumerics.substring(s,parseInt(s+3));
sRev = sFwd.strReverse();
if(
(modelValue.indexOf(sFwd) != -1 && modelValue != "") ||
(modelValue.indexOf(sRev) != -1 && modelValue != "")
)
{
numericFail = true;
}
}
if(numericFail)
{
console.log("Failed sequential numeric character check");
ctrl.$setValidity('serialNumeric', false);
return false;
}
// Look for consecutive letters
for (var s=0; s < 26; s++)
{
testCase = Array(4).join(sAlphas.substring(s,parseInt(s+1)));
if(
(modelValue.indexOf(testCase) != -1 && modelValue != "") ||
(modelValue.indexOf(testCase.toUpperCase()) != -1 && modelValue != "")
)
{
alphaConsecFail = true;
}
}
if(alphaConsecFail)
{
console.log("Failed consecutive alpha character check");
ctrl.$setValidity('consecutiveAlpha', false);
return false;
}
// Look for consecutive numbers
for (var s=0; s < 10; s++)
{
testCase = Array(4).join(sNumerics.substring(s,parseInt(s+1)));
if(modelValue.indexOf(testCase) != -1 && modelValue != "")
{
numericConsecFail = true;
}
}
if(numericConsecFail)
{
console.log("Failed consecutive number character check");
ctrl.$setValidity('consecutiveNum', false);
return false;
}
// Look for consecutive symbols
for (var s=0; s < 10; s++)
{
testCase = Array(3).join(sSymbols.substring(s,parseInt(s+1)));
if(modelValue.indexOf(testCase) != -1 && modelValue != "")
{
symbolConsecFail = true;
}
}
if(symbolConsecFail)
{
console.log("Failed consecutive symbol character check");
ctrl.$setValidity('consecutiveSym', false);
return false;
}
console.log("Succeeded vaidation");
ctrl.$setValidity('alphaUpper', true);
ctrl.$setValidity('alphaLower', true);
ctrl.$setValidity('numeric', true);
ctrl.$setValidity('serialAlpha', true);
ctrl.$setValidity('serialNumeric', true);
ctrl.$setValidity('consecutiveAlpha', true);
ctrl.$setValidity('consecutiveNum', true);
ctrl.$setValidity('consecutiveSym', true);
return true;
}
}
};
}]);
If I attach this to 2 different form fields inside the same HTML template for some reason instead of validating them separately like I expected it seems to validate both of them at the same time which basically breaks the validation. I don't understand what I need todo to get them to validate separately.
Thoughts?
Upvotes: 0
Views: 227
Reputation: 9820
While I already gave a correct answer to @jsonmurphy I found that the following also works.
return {
restrict: "A",
require: '^ngModel',
link: function($scope, $element, $attrs, ctrl){
...
}
}
Upvotes: 0
Reputation: 1600
Perhaps you could isolate the scope of the directive by setting scope: true
in the object returned:
return {
restrict: "A",
scope: true,
require: 'ngModel',
link: function($scope, $element, $attrs, ctrl){
...
}
}
More info: angularjs directive scope default value?
Upvotes: 1