Changing the css class through form validation in AngularJS - javascript

I have an form with 3 input fields, who will validate. Important is to change the error respectively success class when the user does an interaction with the form.
<form class="form-horizontal" name="myForm" novalidate>
<div class="form-group-sm has-feedback" ng-class="{ 'has-error' : myForm.Name.$invalid && !myForm.Name.$pristine || myForm.Name.$touched }">
<label class="control-label" for="name-id">Name</label>
<input type="text"
class="form-control"
placeholder="Name"
name="Name"
ng-model="selected.name"
ng-pattern="/^[a-zA-Z]+/"
ng-required="true"
/>
<p class="help-block" ng-show="myForm.Name.$error.required && myForm.Name.$touched">Name is required</p>
<p class="help-block" ng-show="myForm.Name.$error.pattern">Name must be written with letters</p>
</div>
...
When the user considered the required field and the pattern then after the interaction with the input field, it should be changes the css class to has-success.
I've tried this:
<div class="form-group-sm has-feedback" ng-class="myForm.Name.$invalid && !myForm.Name.$pristine && myForm.Name.$touched ? 'has-error' : 'has-success'">
...
But it doesn't work correctly. Can anyone help me?
I've found the solution. Here is my code:
<div class="form-group-sm has-feedback" ng-class="{ 'has-error' : myForm.Name.$invalid && !myForm.Name.$pristine && myForm.Name.$touched, 'has-success' : myForm.Name.$valid }">
...
</div>

Try it this way:
<div class="form-group-sm has-feedback" ng-class="{'has-error': myForm.Name.$invalid && !myForm.Name.$pristine && myForm.Name.$touched}">

I would recomment a directive like this, as it makes your html a lot shorter.
/* Attach this to input fields to replicate the foundation abide behaviour for invalid form inputs
* Marks the parent with class 'error' and toggles ng-hide on all elements with class error within
* the parent element of the input */
.directive('ppHasError', [function() {
return {
restrict: 'A', //attribute only
require: '?ngModel',
link: function(scope, element, attrs, ngModel) {
var formName = element.parents('form[name]').attr('name');
if( !ngModel )
return;
var parent = element.parent();
if(parent.is('label'))
parent = parent.parent();
var errEl = parent.find('.error');
scope.$watchGroup([formName + '.' + ngModel.$name + '.$invalid', formName + '.' + ngModel.$name + '.$touched'], function(newValues, oldValues) {
var isInvalid = newValues[0];
var touched = newValues[1];
var isError = isInvalid && touched;
parent.toggleClass('error', isError);
errEl.toggleClass('ng-hide', !isError);
});
}
};
}])
which can be used like that:
<div class="medium-10 small-9 columns">
<label>{{ 'card_number' | translate }}</label>
<input class="card-number" name="creditcardNumber" ng-model="paymentInfo.creditcardNumber" size="20" placeholder="4111111111111111" type="text"
pp-has-error required="true">
<small class="error">
{{ 'card_number_error' | translate }}
</small>
</div>
It will set the CSS class 'error' on the parent div and toggle the small.error tag using the ng-hide CSS class.

Related

How to change validation of password with another input in AngularJS?

I have 3 input like this:
<div class="form-group">
<label for="username">Username</label>
<input type="text"
ng-model="formModel.username"
class="form-control"
id="username"
name="username"
required>
<span class="help-block"
ng-show="myForm.username.$error.required && myForm.username.$dirty">
Required
</span>
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password"
class="form-control"
id="password"
name="password"
ng-model="formModel.password"
required
valid-my-password>
<span class="help-block"
ng-show="myForm.password.$error.required && myForm.password.$dirty">
Required
</span>
<span class="help-block"
ng-show="!myForm.password.$error.required &&
myForm.password.$error.sameAs && myForm.password.$dirty || myForm.username.$dirty">
Username and password are similar
</span>
</div>
<div class="form-group">
<label for="password_c">Approve password</label>
<input type="password"
class="form-control"
id="password_c"
name="password_c"
ng-model="formModel.password_c"
required
valid-password-c />
<span class="help-block"
ng-show="myForm.password_c.$error.required && myForm.password_c.$dirty">
You need to approve the password
</span>
<span class="help-block"
ng-show="!myForm.password_c.$error.required && myForm.password_c.$error.noMatch &&
myForm.password.$dirty">
Passwords don't match
</span>
</div>
And the validation works great. but:
1. if the password are similar to the username, and I try to change the username, the alert dosn't dissaper.
2. if the password and the confirm password input are filled and the validation is okay, and i'm trying to change the password, the alert of "Passwords don't match" doesn't show.
jsFiddle
Just change your error validations with snippets below
<span class="help-block" ng-show="!myForm.password.$error.required &&
myForm.password.$error.sameAs && myForm.password.$dirty && formModel.password==formModel.username">
Username and password are similar
</span>
<span class="help-block" ng-show="!myForm.password_c.$error.required && myForm.password_c.$error.noMatch &&
myForm.password.$dirty && formModel.password_c!=formModel.password">
Passwords don't match
</span>
Here is the updated link of your fiddle
http://jsfiddle.net/vz215k94/
I found my answer. I add another directive called "validMyUsername" and i call him from the username input. In this directive i change the password validation.
and for the confirm password I change in the password directive the validation.
like this:
The username input directive:
...
directive('validMyUsername', function () {
return {
require: 'ngModel',
link: function (scope, elm, attrs, ctrl) {
ctrl.$parsers.unshift(function (viewValue, $scope) {
var sameAs = viewValue != scope.myForm.password.$viewValue
scope.myForm.password.$setValidity('sameAs',sameAs);
ctrl.$setValidity('sameAs',sameAs);
return viewValue;
})
}
}
The password directive:
...
directive('validMyPassword', function () {
return {
require: 'ngModel',
link: function (scope, elm, attrs, ctrl) {
ctrl.$parsers.unshift(function (viewValue, $scope) {
var sameAs = viewValue != scope.myForm.username.$viewValue
var noMatch = viewValue != scope.myForm.password_c.$viewValue
scope.myForm.password_c.$setValidity('noMatch',!noMatch);
ctrl.$setValidity('sameAs', sameAs)
return viewValue;
})
}
}
})
Here is the full example: jsFiddle

Using AngularJS ngModel and Form Validation to $watch two elements and test if they are equal whenever either input changes

What I am trying to do is create a directive which compares two password inputs and triggers invalid if either changes. I have found a few examples and have tried a few and have combined a few in my own attempts. However, I have only been able to toggle the validity with $setValidity when the confirm password field changes. When you change the password field it doesn't trigger the invalidity of the comparison.
Here's my directive:
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 + '_' + scope.$view;
}
return combined;
}, function(value) {
if (value) {
ctrl.$parsers.unshift(function(viewValue) {
var origin = scope.passwordVerify;
if (origin !== viewValue) {
ctrl.$setValidity("pwd", false);
return undefined;
} else {
ctrl.$setValidity("pwd", true);
return viewValue;
}
});
}
});
}
};
});
Here's the directive in action:
<input id="user_password" type="password" name='user_password' placeholder="password" value='' required ng-model="user.user_password">
<p class="help-text">Required</p>
<div class="help-block" ng-messages="add_user_form.user_password.$error" ng-show="add_user_form.user_password.$touched">
<div ng-messages-include="/app/views/messages.html" ></div>
<input id="confirm_password" ng-model="user.confirm_password" name="confirm_password" type="password" placeholder="confirm password" name="user_confirm_password" required password-verify="user.user_password">
<p class="help-text">Enter matching password</p>
<div class="help-block" ng-messages="add_user_form.confirm_password.$error" ng-show="add_user_form.confirm_password.$touched">
<div ng-messages-include="/app/views/messages.html" ></div>
With this code I can verify that the passwords match when I change the value of the confirm password field, however when you change the value of the password field it doesn't revalidate the input. I'm pretty sure there is a successful way to add $watch to two elements or to use $watchgroup to do this. I just can't figure it out. I know there are a lot of questions on this topic but all I've tried have only gotten me to this point.
I'm using Angular 1.5.7 btw...
Here's a version working bi-directionally:
(function() {
"use strict";
angular.module('app', ['ngMessages'])
.controller('mainCtrl', function($scope) {
})
.directive('passwordVerify', 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('passwordVerify', function(val) {
validate();
});
var validate = function() {
// values
var val1 = ngModel.$viewValue;
var val2 = attrs.passwordVerify;
// set validity
ngModel.$setValidity('passwordVerify', !val1 || !val2 || val1 === val2);
};
}
}
})
})();
<html ng-app="app">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-messages/1.5.7/angular-messages.min.js"></script>
</head>
<body ng-controller="mainCtrl">
<form name="add_user_form">
<div class="col-md-12">
<div class="form-group" ng-class="{ 'has-error' : add_user_form.user_password.$touched && add_user_form.user_password.$invalid }">
<p class="help-text">Enter password</p>
<input type="password" class="form-control" id="user_password" name="user_password" placeholder="password" required ng-model="user.user_password" password-verify="{{user.confirm_password}}">
<div class="help-block" ng-messages="add_user_form.user_password.$error" ng-show="add_user_form.user_password.$touched">
<p ng-message="required">This field is required</p>
<p ng-message="minlength">This field is too short</p>
<p ng-message="maxlength">This field is too long</p>
<p ng-message="required">This field is required</p>
</div>
</div>
<div class="form-group" ng-class="{ 'has-error' : add_user_form.confirm_password.$touched && add_user_form.confirm_password.$invalid }">
<p class="help-text">Enter matching password</p>
<input class="form-control" id="confirm_password" ng-model="user.confirm_password" name="confirm_password" type="password" placeholder="confirm password" required password-verify="{{user.user_password}}">
<div class="help-block" ng-messages="add_user_form.confirm_password.$error" ng-show="add_user_form.confirm_password.$touched">
<p ng-message="required">This field is required</p>
<p ng-message="minlength">This field is too short</p>
<p ng-message="maxlength">This field is too long</p>
<p ng-message="required">This field is required</p>
<p ng-message="passwordVerify">No match!</p>
</div>
</div>
</div>
</form>
</body>
</html>
I hope it helps.

How to hide field and use ng-model for Rest Service?

I have field that i want to hide permanently from the view but i want to use ng-model for Rest Service to do some calculation for other fields. How to achieve that task using AngularJS ?
So far tried code...
main.html
<div class="form-group col-md-6" ng-disabled="disableEffComp" ng-hide="true">
<div>
<label class="control-label" for="controlEffect">Overall
Control Effectiveness Computed</label>
</div>
<select kendo-drop-down-list k-data-value-field="'id'"
k-data-text-field="'text'" k-option-label="'Select'"
k-data-source="ctrlEffOptions"
ng-model-options="{ updateOn: 'blur' }"
ng-model="processRating.controlEffectivenessRatingComputeKey"
readOnly="compReadOnly" id="controlEffect">
</select>
</div>
mainCtrl.js
$scope.overrideBusinessDec = function () {
if ($scope.processRating.controlEffectivenessRatingComputeKey && $scope.processRating.controlEffectivenessRatingOverrideKey !== $scope.processRating.controlEffectivenessRatingComputeKey) {
Rating.getProcessRatingFields($scope.processRating.controlEffectivenessRatingOverrideKey, $scope.processRating.finalOutcomeInherentRiskRatingKey).then(function (response) {
$scope.processRating.residualRiskRatingComputeKey = response.data.residualRiskRatingComputeKey;
$scope.processRating.residualRiskRatingOverrideKey = response.data.residualRiskRatingComputeKey;
$scope.riskBusinessOptions = response.data.residualRiskOverride;
});
}
};

multiple checkbox validation in angular js

libraryApp.directive("checkboxGroup", function() {
return {
restrict: "A",
link: function(scope, elem, attrs) {
// Determine initial checked boxes
if (scope.groupArray.indexOf(scope.item.id) !== -1) {
elem[0].checked = true;
}
// Update array on click
elem.bind('click', function() {
var index = scope.groupArray.indexOf(scope.item.id);
// Add if checked
if (elem[0].checked) {
if (index === -1) scope.groupArray.push(scope.item.id);
}
// Remove if unchecked
else {
if (index !== -1) scope.groupArray.splice(index, 1);
}
// Sort and update DOM display
scope.$apply(scope.groupArray.sort(function(a, b) {
return a - b
}));
});
}
}
});
angular js and bootstrap
<form class="userForm" name="userForm" novalidate ng-init="">
<notifications></notifications>
<section>
<div class="row">
<div class="col-md-11">
<div class="form-group" style="display: flex;" ng-class="{ 'has-error' :(userForm.status.$dirty && userForm.status.$error.required) alert(ram)}" >
<label class="assetDropdownLabel col-md-2" for="manufacturer">Permission<span class="text-danger">*</span></label>
<div ng-repeat="item in list" id="status" name="status" ng-model="status" required ng-required="true" >
<label style="margin-right:12px"><input type="checkbox" style="display:inline; width: 18px;margin:0px" checkbox-group required />{{item.value}}</label>
</div>
<div ng-show="userForm.status.$dirty && userForm.status.$error.required" class="help-block col-md-offset-2">Required field</div>
</div>
</div>
</div>
</section>
<div class="btnContainer addUserBtn" >
<button type="button" ng-click="finalValidation()" class="pull-right primarybutton btn_small addmargintopbottom" alt="{{buttonTitle}}" ng-disabled="userForm.$error.pattern">{{buttonTitle}}</button>
</div>
</form>
I want to check validation for checkbox for required; atleast one checkbox needs to be selected then there will be no message or ng-class added in noticification. If no checkbox selected then on finalvalidation() or ng-class should be added

How to set input state angularjs

I have some form with angularjs valid/invalid states.
<div class="form-group" ng-class="{ 'has-error' : createForm.name.$invalid && !createForm.name.$pristine , 'has-success': createForm.name.$valid}">
<label>Name</label>
<input type="text" name="name" class="form-control" ng-model="$parent.filterName" ng-minlength="1" required/>
<span ng-show="createForm.name.$invalid && !createForm.name.$pristine">Name shouldn't be empty</span>
<span ng-show="isDublicateColumn($parent.filterName)">Name already exists</span>
</div>
How do I set input to invalid state based on result of isDublicateColumn($parent.filterName) ?
Or is any better way to change bootstrap state to 'has-error' when isDublicateColumn($parent.filterName) return true ?
Should do the job
<div class="form-group" ng-class="{
'has-error' : (isDublicateColumn($parent.filterName) || createForm.name.$invalid && !createForm.name.$pristine) ,
'has-success': createForm.name.$valid}">
If you use <form> instead of <div>, an alternative solution is to create a custom validation directive.
app.directive('noDuplicateColumn', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, modelCtrl) {
modelCtrl.$parsers.unshift(function(viewValue) {
var isValid = !scope.isDublicateColumn(viewValue);
modelCtrl.$setValidity('duplicateColumn', isValid);
return isValid ? viewValue : undefined;
});
}
};
});
and put it at your input:
<input type="text" name="name" class="form-control" ng-model="filterName" ng-minlength="1" required no-duplicate-column />
For the full example see: http://plnkr.co/edit/O7MZX8lAk6lUjHnkgnVG?p=preview

Categories