I'm dealing with a standard "change your password" form where you have two fields: password1 and password2. Those two fields are just to validate that the user enter the right password and they need to contain the same text.
I added a directive to validate password but now I want that, if both fields are not equal between each other, make both fields become invalid and not just the one I'm typing in. Can I do that?
I try to call the $setValidity on both ngmodels but I'm not finding the way to call from one ctrl.$parsers.unshift or directive link function the $setValidity or the other field I'm not currently validating. I'm really lost..
Thanks a lot!
My directive is:
myApp.directive('validatepassword', function () {
return {
require: 'ngModel',
restrict: 'A', // only activate on element attribute
link: function (scope, elm, attrs, ngModel) {
ngModel.$parsers.unshift(function (viewValue) {
var valPasswordValue = attrs.validatepassword;
var otherPassword = $('#' + valPasswordValue)[0].value;
var valido = scope.validatePassword(viewValue, otherPassword);
ngModel.$setValidity('password', valido);
return viewValue;
});
}
};
});
and I'm using in this way in the code:
<div class="control-group">
<label class="control-label" for="inputPassword1">Password</label>
<div class="controls">
<input id="inputPassword1" name="inputPassword1" type="password" ng-model="context.Password" required validatepassword="inputPassword2"/>
<span class="alert-danger invalid-form" ng-show="!addEditForm.inputPassword1.$valid">(*)</span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="inputPassword2">Repeat Password</label>
<div class="controls">
<input id="inputPassword2" name="inputPassword2" type="password" ng-model="context.Password2" required validatepassword="inputPassword1"/>
<span class="alert-danger invalid-form" ng-show="!addEditForm.inputPassword2.$valid">(*)</span>
</div>
</div>
Any ideas about how can I validate both fields as soon as one of them change?
Thanks a lot!
To trigger the validation method from one field in another field I had to manually set the value of the other field. You can do that inside of a ng-change:
ng-change="addEditForm.inputPassword2.$setViewValue(addEditForm.inputPassword2.$viewValue)"
When you do that it should trigger the validation in both password fields.
You could also access the fields inside of your directive like so:
scope.addEditForm.inputPassword1
So you could get rid of the jQuery access inside of your directive.
Here is the HTML-partial that worked for password validation on both fields:
<div class="control-group">
<label class="control-label" for="inputPassword1">Password</label>
<div class="controls">
<input id="inputPassword1" name="inputPassword1" type="password" ng-model="context.Password" required
validatepassword="inputPassword2" ng-change="addEditForm.inputPassword2.$setViewValue(addEditForm.inputPassword2.$viewValue)"/>
<span class="alert-danger invalid-form" ng-show="!addEditForm.inputPassword1.$valid">(*)</span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="inputPassword2">Repeat Password</label>
<div class="controls">
<input id="inputPassword2" name="inputPassword2" type="password" ng-model="context.Password2" required
validatepassword="inputPassword1" ng-change="addEditForm.inputPassword1.$setViewValue(addEditForm.inputPassword1.$viewValue)"/>
<span class="alert-danger invalid-form" ng-show="!addEditForm.inputPassword2.$valid">(*)</span>
</div>
</div>
Angular-UI has a built-in validator which you can use in various purpose, there is a exact example of password and confirm password which you can check:
https://github.com/angular-ui/ui-utils/blob/master/modules/validate/demo/index.html#L29
Please check this fiddle
http://jsfiddle.net/vigneshvdm/Dnt7w/5/
you can do something like this
var password=$("#telephone").val();
var reenteredpassword=$("#mobile").val();
if(password==reenteredpassword)
{
$("#required").html("Passwords Match");
}
else
{
$("#required").html("Passwords do not Match");
}
Related
I have a form with password field for which I implemented a password directive.
I currently implemented only 1 validation but I've a list of validations on the field.
I want them to displayed in either red or green depending on valid/invalid respectively - when the user starts typing into the field. If the users control goes out of the box AND all validations are passed, I want to set the field to valid and set it to pristine so that the validation list won't show up.
However if any of the validations fail, I want all of them to be seen even if the field is out of focus. Below is my snippet for the form group.
<div class="form-group">
<label for="inputPass" class="col-sm-3 control-label text-sm text-left">Password</label>
<div class="col-sm-9">
<input type="password" placeholder="Password"
class="form-control" ng-model="registerAccount.password"
required name="inputPass" id="inputPass"
password ng-blur="form.inputPass.$invalid ? return: form.inputPass.$setPristine">
<div ng-show="form.inputPass.$dirty" class="help-block">
<p class="text-danger" ng-show="form.inputPass.$error.required">
Password is required.
</p>
<p ng-class="form.inputPass.$error.invalidLength ? 'text-danger' : 'text-success'">
Password should be atleast 8 characters.
</p>
</div>
</div>
</div>
Following is my directive
'use strict';
angular.module('nileLeApp')
.directive('password', function () {
return {
restrict: 'A',
require: 'ngModel',
link: function ($scope, $element, $attrs, ngModelCtrl) {
$scope.$watch($attrs.ngModel, function (value) {
if (value) {
var length = (value.length >= 8);
ngModelCtrl.$setValidity('invalidLength', length);
}
});
}
};
});
When the focus out of the field, the validation list is still showing up. I was expecting it to be hidden because the field is being set to pristine. Any ideas ? I wanted it to be similar to password field in https://dl.dropboxusercontent.com/u/636000/password_verification/index.html. As the user types the password, the validations are reflected in red/green.
You are not calling $setPristine method. Should be form.inputPass.$setPristine():
ng-blur="form.inputPass.$invalid ? return: form.inputPass.$setPristine()"
or cleaner variation:
ng-blur="form.inputPass.$valid && form.inputPass.$setPristine()"
You may not need to use a special directive:
<form name="testForm">
<input ng-model="testVal" name="testVal" required ng-minlength="3" ng-maxlength="10" ng-pattern="/^\w+$/">
<div ng-show="testForm.$invalid">
<div ng-class="{'errors':testForm.testVal.$error.required,'success':!testForm.testVal.$error.required}">Required</div>
<div ng-class="{'errors':testForm.testVal.$error.minlength,'success':!testForm.testVal.$error.minlength}">Minlength</div>
<div ng-class="{'errors':testForm.testVal.$error.maxlength,'success':!testForm.testVal.$error.maxlength}">Maxlength</div>
<div ng-class="{'errors':testForm.testVal.$error.pattern,'success':!testForm.testVal.$error.pattern}">Pattern</div>
</div>
</form>
This code does the same thing and given you the link: dl.dropboxusercontent.com/u/636000/password_verification/index.html
If you need to establish a more sophisticated checks, you can use the following directive use-form-error:
Live example on JsFiddle
<form name="testForm">
<input ng-model="testVal" name="testVal" required ng-minlength="3" ng-maxlength="10" ng-pattern="/^\w+$/" use-form-error="containWow" use-error-expression="testVal.indexOf('wow')>-1">
<div ng-show="testForm.$invalid">
<div ng-class="{'errors':testForm.testVal.$error.required,'success':!testForm.testVal.$error.required}">Required</div>
<div ng-class="{'errors':testForm.testVal.$error.minlength,'success':!testForm.testVal.$error.minlength}">Minlength</div>
<div ng-class="{'errors':testForm.testVal.$error.maxlength,'success':!testForm.testVal.$error.maxlength}">Maxlength</div>
<div ng-class="{'errors':testForm.testVal.$error.pattern,'success':!testForm.testVal.$error.pattern}">Pattern</div>
<div ng-class="{'errors':testForm.testVal.$error.containWow,'success':!testForm.testVal.$error.containWow}">It's 'wow' contains</div>
</div>
</form>
This is my first time using AngularJS, and the form validation is making me question my sanity. You would think this would be the easy part, but no matter how many ways I've tried Googling, the only thing that works is if I set a flag inside my controller's submit if the form is invalid to set the error class. I've looked at similar problems here, but none of them helped, so please do not simply dismiss this as a potential duplicate. Everything else has been a fail.
In the example mark up below I have reduced my form down to just one element. Here is what I have observed:
Using only $error.required does work. The ng-class { 'has-error' :registerForm.firstName.$error.required} does outline the text box with the bootstrap has-ertror class, but this is on form load, which I do not want.
The <p> element with the error message will exhibit the same behavior, so I know that the message exists and is not malfored. It will also display if I only use $error.required. But as soon as I add && registerForm.$submitted ( or $isdirty or !notpristine ) the message will not display on form submit. There are no errors (have developers tools open in chrome) and will post to the web API with no problem and return ok 200 or 400 if I send bad params.
I can write validation code inside my controller, checking if the field has a value and setting a flag on $scope such as $scope.firstNameIsRequired and that will work fine setting ng-show="$scope.firstNameIsRequired", but that will remove testability.
So the problem definitely has to be with how I am adding this in the markup. But after a weekend spent googling I am at my wits end. The only other thing different is that I am using a span on a click element to submit the form instead of an input = submit, but the registerForm.$valid function is setting the correct value. Do I somehow need to trigger the form validation in that ng-click directive?
I am using angular.js v 1.4.8.
I do have angular ui which has it's own validate, but that shouldn't interfere with the basic validation.
Here is the simplified markup:
<form name="registerForm" class="form-group form-group-sm"
ng-controller="userAccountController" novalidate>
<div class="form-group"
ng-class="{ 'has-error' : registerForm.firstName.$error.required }">
<div><label>First Name</label> </div>
<input type="text" class="form-control" id="firstName" name="firstName" value=""
ng-model="firstName" placeholder="First Name" maxlength="100" required=""/>
<p ng-show="registerForm.firstName.$error.required && registerForm.$submitted"
class="alert alert-danger">First Name is required</p>
</div>
<div>
<span class="btn btn-default"
ng-click="submit(registerForm.$valid)">Register</span>
</div>
My controller code is
angular.module( "Application" ).controller( "userAccountController", [
"$scope", "userAccountService", function ( $scope, userAccountService)
{
$scope.hasErrors = false;
$scope.errorMessages = "";
$scope.emailExists = true;
$scope.clearErrors = function (){
$scope.hasErrors = false;
}
$scope.onSuccess = function ( response ) {
alert( "succeeded" );
}
$scope.submit = function (isValid) {
if ($scope.registerForm.$invalid)
return;
alert("isvalid");
$scope.clearErrors();
var userProfile = $scope.createUser();
userAccountService.registerUser(userProfile, $scope.onSuccess, $scope.onError);
}
$scope.createUser = function () {
return {
FirstName: $scope.firstName, LastName: $scope.lastName, Email: $scope.email,
Password: $scope.password, SendAlerts: $scope.sendAlerts
};
};
}
]);
Any help will be appreciated. I probably just need a second set of eyes here because I have been dealing with this on and off since late Friday.
in angular you want use the element.$valid to check wheter an model is valid or not - and you use element.$error.{type} to check for a specific validation error.
Keep in mind that the form.$submitted will only be set if the form is actually submitted - and if it has validationerrors it will not be submitted (and thus that flag is still false)
If you want to show errors only on submit you could use a button with type="submit" and bind to ng-click event - and use that to set a flag that the form has been validated. And handling the submit if the form is valid.
A short example with 2 textboxes, having required and minlength validation:
angular.module("myApp", [])
.controller("myFormController", function($scope) {
$scope.isValidated = false;
$scope.submit = function(myForm) {
$scope.isValidated = true;
if(myForm.$valid) {
console.log("SUCCESS!!");
}
};
});
.form-group {
margin: 10px;
padding: 10px;
}
.form-group.has-error {
border: 1px solid red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
<div ng-app="myApp" ng-controller="myFormController">
<form name="myForm">
<div class="form-group" ng-class="{'has-error': myForm.name.$invalid && isValidated}">
<span>Name:</span>
<input type="text" name="name" minlength="5" ng-model="name" required />
<span ng-if="myForm.name.$error.required && isValidated">Name is required</span>
<span ng-if="myForm.name.$error.minlength && isValidated">Length must be atleast 5 characters</span>
</div>
<div class="form-group" ng-class="{'has-error': myForm.email.$invalid && isValidated}">
<span>Email:</span>
<input type="text" name="email" minlength="5" ng-model="email" required />
<span ng-if="myForm.email.$error.required && isValidated">Email is required</span>
<span ng-if="myForm.email.$error.minlength && isValidated">Length must be atleast 5 characters</span>
</div>
<button type="submit" ng-click="submit(myForm)">Submit</button>
</form>
</div>
I have two questions that are related:
First: I have the following directive, who's purpose is to validate whether an input[type=file] is valid or not, however I have no idea how it does it least of all, what the actual code means, here it is:
angular.module('sccateringApp')
.directive('fileModel', ['$parse', function($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function(){
scope.$apply(function(){
modelSetter(scope, element[0].files[0]);
});
});
}
};
}]);
Like I said, I have no idea what the above code actually does, the explanation I got from the forum where I copied that was that it validated an input type file. Is this correct? (So far I haven't been able to verify if it works or not since it doesn't work with the code I'm using at the moment to validate my forms).
Second: Having the form below, using angular form validation it doesn't allow the submit button to be clicked until the actual inputs inside the form match the validation rules (enter a name for the category, and the description should have a max length of 144 characters). I included the directive into the file input, however the actual ng-model for the form ignores the required in the input type file and just verifies the rules are met for the first two inputs.
Here is my form:
<form method="post" role="form" name="newCategoryForm" ng-submit="submitForm()" enctype="multipart/form-data" novalidate>
<div class="row">
<div class="row">
<div class="col s12">
<div input-field>
<input type="text" name="cat-name" id="cat-name" ng-class="{ 'ng-invalid' : newCategoryForm.catname.$invalid && !newCategoryForm.catname.$pristine }"
ng-model="catname" required>
<label>Nombre</label>
</div>
</div>
</div>
<div class="row">
<div class="col s12">
<div input-field>
<textarea class="materialize-textarea" name="cat-description" id="cat-description" length="144"
ng-model="catdescription" ng-maxlength="144" required></textarea>
<label>Descripción</label>
</div>
</div>
</div>
<div class="row">
<div class="col s12">
<h6>Imagen de Fondo</h6>
<div class="file-field input-field">
<div class="btn pink darken-2 waves-effect waves-light">
<span>Archivo</span>
<input type="file" name="cat-bgimg" id="cat-bgimg"
file-model="variable" required>
</div>
<div class="file-path-wrapper">
<input class="file-path" type="text">
</div>
</div>
</div>
</div>
</div>
<button type="submit" class="btn btn-large pink darken-2 waves-effect waves-light center-button" ng-disabled="newCategoryForm.$invalid">Crear Categoría</button>
</form>
The first two inputs get validated correctly, the third one (file input) doesn't and I don't really know why since the directive got included on the input (I know natively, ngModel doesn't validate file inputs).
Any ideas or suggestions of how can I fix this? I'm really new to Angular, and all the tutorials are pretty much useless. I come from 5 years of experience working on jQuery, and the transition to Angular hasn't been easy at all.
The directive posted above is used to make the submit get the data found in the <input type="file"></input>.
Also, a variable should be initialized in the controller so that the values found inside the form are copied to said variable, then this variable needs to be sent as a parameter inside the ng-submit="submitForm().
Example:
angular.module('sccateringApp')
.controller('newSubcategoryController', function (httpcalls, $scope) {
...
$scope.subcategory = [];
...
$scope.submitForm = function(subcategory){
...
$scope.request.insertSubcategory(subcategory);
}
});
Each ng-model inside the form would be:
<input type="text" ng-model="category.name">
So that the category variable found in the controller acquires that value.
I had a input field in my form that have the following class:
class="form-group field-sale-first_name required"
and after client side validation it can have one of two different classes added to it.
class="form-group field-sale-first_name required has-success"
or
class="form-group field-sale-first_name required has-error"
I'm trying to catch when this class has success of error status with jQuery method hasClass() but always getting True even when the .has-error or the has-success are not there.
<form id="checkout-form" action="/site/checkout" method="post">
<div class="form-group field-sale-first_name required">
<input type="text" id="sale-first_name" class="form-control" name="Sale[first_name]" placeholder="First Name">
and the script:
clientValidationStatus = (function() {
if ($("form-group.field-sale-first_name.required").hasClass(".has-success)) {
alert("Success");
}
})();
Could someone give a hint of how to get this change?
Thanks in advance.
You are missing hasClass syntax hasClass("has-success") and for form-group
clientValidationStatus = (function() {
if ($(".form-group.field-sale-first_name.required").hasClass("has-success")) {
alert("Success");
}
})();
i'm on my web site project and it seems that my jquery function doesn't work
.i have to validate this:if the user enters <<nom de famille du pere>>,<<prenom du pere>> has to be entered too.This is my html code:
<div class="form-group">
<div class="col-md-6">
<label class="col-md-4 control-label" for="father">Nom de famille du père </label>
<input id="father" name="father" type="text" class="form-control input-md" >
</div>
</div><br/><br/><br/>
<div class="form-group">
<div class="col-md-6">
<label class="col-md-4 control-label" for="ffather">Prénom du père</label>
<input id="ffather" name="ffather" type="text" class="form-control input-md">
</div>
</div><br/><br/><br/>
and this is my jquery function :
$(document).ready(function() {
$('#father').submit(function() {
if ($(this)).is(':empty')) {
$('#ffather').prop('required',false);
}
else{
$('#ffather').prop('required',true);
}} }
DEMO: http://jsfiddle.net/Lfnrrdfu/1/
you have a few mistakes in your code:
$('#father').on('keyup', function () {
if (!$(this).val()) {
$('#ffather').prop('required',false);
}
else{
$('#ffather').prop('required',true);
}
console.log($('#ffather').prop('required'));
});
You can't use submit event with an input, submit is for a form, you could use the form but then you have to prevent default then check the value of the input.
You are trying to set the attributes upon form submission, which is not the right way to do it. You should only check if the fields satisfy the requirements on submit. Defining the constrains should be on the markup. If you are not using any custom form validator, you can use HTML constrain validation. Examples can be found here
http://www.w3schools.com/js/js_validation.asp
Again, the jQuery submit event can ONLY be attached to form elements. Review here https://api.jquery.com/submit/