THE SITUATION:
I am using ng-messages directive for instant validation in my angular app. Everything is working fine except one thing: i need to validate the field 'password confirmation' and don't know how to do.
THE CODE:
<form name="autentication_form" novalidate="" ng-submit="submit_register()">
<label class="item item-input">
<span class="input-label">Email</span>
<input type="text" name="email" ng-model="registerData.email" required>
<div class="form-errors" ng-messages="autentication_form.email.$error" role="alert" ng-if='autentication_form.email.$dirty'>
<div class="form-error" ng-message="required">You did not enter the email</div>
</div>
</label>
<label class="item item-input">
<span class="input-label">Password</span>
<input type="password" name="password" ng-model="registerData.password" required>
<div class="form-errors" ng-messages="autentication_form.password.$error" role="alert" ng-if='autentication_form.password.$dirty'>
<div class="form-error" ng-message="required">Please enter the password</div>
</div>
</label>
<label class="item item-input">
<span class="input-label">Password confirmation</span>
<input type="password" name="password_confirmation" ng-model="registerData.password_confirmation" required>
<div class="form-errors" ng-messages="autentication_form.password_confirmation.$error" role="alert" ng-if='autentication_form.password_confirmation.$dirty'>
<div class="form-error" ng-message="required">Password confirmation required</div>
</div>
</label>
</form>
THE QUESTION:
How can i check that the password confirmation match using ng-messages?
Require the ngModel controller.
Add a method to the ngModel controller’s $validators object. Angular will invoke the function when the model value changes. The function returns a boolean, and a return value of false will set the corresponding ngModel’s $error property automatically.
The compare-to directive looks like the following:
var compareTo = function() {
return {
require: "ngModel",
scope: {
otherModelValue: "=compareTo"
},
link: function(scope, element, attributes, ngModel) {
ngModel.$validators.compareTo = function(modelValue) {
return modelValue == scope.otherModelValue;
};
scope.$watch("otherModelValue", function() {
ngModel.$validate();
});
}
};
};
module.directive("compareTo", compareTo);
You can use the directive inside of markup like so:
<input type="password" name="confirmPassword"
ng-model="registration.user.confirmPassword"
required
compare-to="registration.user.password" />
<div ng-messages="registrationForm.confirmPassword.$error"
ng-messages-include="messages.html"></div>
The best approach is to use a directive. The major point of problem here is that both password and password confirmation inputs need to be watched.
Here's the solution that could help
angular.module('app', ['ngMessages'])
.controller('ctrl', function($scope) {
$scope.registerData = {};
})
.directive('confirmPwd', function($interpolate, $parse) {
return {
require: 'ngModel',
link: function(scope, elem, attr, ngModelCtrl) {
var pwdToMatch = $parse(attr.confirmPwd);
var pwdFn = $interpolate(attr.confirmPwd)(scope);
scope.$watch(pwdFn, function(newVal) {
ngModelCtrl.$setValidity('password', ngModelCtrl.$viewValue == newVal);
})
ngModelCtrl.$validators.password = function(modelValue, viewValue) {
var value = modelValue || viewValue;
return value == pwdToMatch(scope);
};
}
}
});
<html ng-app="app">
<head>
<script data-require="angular.js@~1.4.3" data-semver="1.4.3" src="https://code.angularjs.org/1.4.3/angular.js"></script>
<script data-require="angular-messages@1.4.3" data-semver="1.4.3" src="https://code.angularjs.org/1.4.3/angular-messages.js"></script>
<script src="https://code.angularjs.org/1.3.15/angular.js"></script>
<script src="script.js"></script>
</head>
<body ng-controller="ctrl">
<form name="autentication_form" novalidate="" ng-submit="submit_register()">
<label class="item item-input">
<span class="input-label">Email</span>
<input type="text" name="email" ng-model="registerData.email" required="" />
<div class="form-errors" ng-messages="autentication_form.email.$error" ng-if='autentication_form.email.$touched'>
<span class="form-error" ng-message="required">You did not enter the email</span>
</div>
</label>
<label class="item item-input">
<span class="input-label">Password</span>
<input type="password" name="password" ng-model="registerData.password" required />
<div class="form-errors" ng-messages="autentication_form.password.$error" ng-if='autentication_form.password.$touched'>
<span class="form-error" ng-message="required">Please enter the password</span>
</div>
</label>
<label class="item item-input">
<span class="input-label">Password confirmation</span>
<input type="password" name="password_confirmation" ng-model="registerData.password_confirmation" required="" confirm-pwd="registerData.password" />
<div class="form-errors" ng-messages="autentication_form.password_confirmation.$error" ng-if='autentication_form.password_confirmation.$touched'>
<span class="form-error" ng-message="required">Password confirmation required</span>
<span class="form-error" ng-message="password">Password different</span>
</div>
</label>
</form>
</body>
</html>