Validate checkbox that which are required - angularjs

I'd like to create terms and conditions form in my angularjs project.
From multiple checkboxes only several are required, and I'd like to enable submit button, only when all required checkboxes are checked.
Here is my checkboxes:
<label class="agreement-label control-label required">Zgoda</label>
<input class="agreements ng-pristine ng-untouched ng-empty ng-invalid ng-invalid-required" id="agreement_1" name="agreement" required="" ng-model="client.agreement[0]" type="checkbox">
<label class="agreement-label control-label">Zgoda 2</label>
<input class="agreements ng-pristine ng-untouched ng-valid ng-not-empty" id="agreement_2" name="agreement" ng-model="client.agreement[1]" type="checkbox">
<label class="agreement-label control-label">Zgoda 4</label>
<input class="agreements ng-pristine ng-untouched ng-valid ng-not-empty" id="agreement_5" name="agreement" ng-model="client.agreement[4]" type="checkbox">
<label class="agreement-label control-label required">Zgoda 5</label>
<input class="agreements ng-pristine ng-untouched ng-empty ng-invalid ng-invalid-required" id="agreement_6" name="agreement" required="" ng-model="client.agreement[5]" type="checkbox">
<button class="btn btn-success" id="ticketFormSubmit" ng-disabled="isAgreementsInvalid()" ng-click="changeButtonValue()" type="submit" disabled="disabled">Zapisz</button>
And in my angular controller:
$scope.isAgreementsInvalid = function() {
return $scope.ticketForm.agreement.$invalid;
}
The problem is, only last required checkbox is validating.

You could do like this, but ng-init is necessary for this solution. name will not be required for this solution.:-
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope) {
$scope.isAllChecked = false;
$scope.checkValid = function() {
$scope.isAllChecked = true
angular.forEach($scope.client.agreement, function(value) {
if (!value) {
$scope.isAllChecked = false;
}
})
}
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<form name="ticketForm">
<label class="agreement-label control-label required">Zgoda</label>
<input ng-init="client.agreement[0] = false;" class="agreements" id="agreement_1" required ng-model="client.agreement[0]" type="checkbox" ng-click="checkValid()">
<label class="agreement-label control-label">Zgoda 2</label>
<input ng-init="client.agreement[1] = false;" class="agreements" id="agreement_2" required ng-model="client.agreement[1]" type="checkbox" ng-click="checkValid()">
<button class="btn btn-success" id="ticketFormSubmit" ng-disabled="!isAllChecked" ng-click="submitFunction()" type="submit" disabled="disabled">Zapisz</button>
</form>
</div>

You could achieve this slightly more succinctly by using some():
$scope.isAgreementsInvalid = function() {
return $scope.ticketForm.agreement.some((item) => item.$invalid);
}

Related

Programmatically apply classes to angularjs form

I have an angular directive to facilitate the adding of bootstrap classes at runtime to streamline the need to apply "form-group", "control-label" and "form-control". This works perfectly as long as I don't try to include multiple levels at once, meaning that I cannot seem to make this work to include multiple divs in "form-group. I have attached the code, raw HTML and processed HTML for review to see if someone might have some insight into how I might modify to make this tool meaningful.
Directive:
(function () {
"use strict";
angular.module("ppac")
.directive("formfix", formfix);
var addClasses = function (element) {
var input = element.querySelector("input, textarea, select");
var type = input.getAttribute("type");
if (type !== "checkbox" && type !== "radio") {
input.classList.add("form-control");
}
var label = element.querySelector("label");
label.classList.add("control-label");
element.classList.add("form-group");
};
function formfix() {
return {
restrict: "A",
link: function (scope, element) {
addClasses(element[0]);
}
}
}
})();
HTML Form:
<form name="contactForm" ng-submit="model.submit()" novalidate>
<div class="form-horizontal">
<div formfix>
<label for="firstName" class="col-md-2">First Name</label>
<div class="col-md-3">
<input type="text" name="firstName" id="firstName" ng-model="model.contact.firstName" />
</div>
<label for="lastName" class="col-md-2">Last Name</label>
<div class="col-md-3">
<input type="text" name="lastName" id="lastName" ng-model="model.contact.lastName" />
</div>
</div>
</div>
</form>
Processed HTML:
<form name="contactForm" ng-submit="model.submit()" novalidate="" class="ng-pristine ng-valid">
<div class="form-horizontal">
<div formfix="" class="form-group">
<label for="firstName" class="col-md-2 control-label">First Name</label>
<div class="col-md-3">
<input type="text" name="firstName" id="firstName" ng-model="model.contact.firstName" class="ng-pristine ng-valid form-control ng-empty ng-touched">
</div>
<label for="lastName" class="col-md-2">Last Name</label>
<div class="col-md-3">
<input type="text" name="lastName" id="lastName" ng-model="model.contact.lastName" class="ng-pristine ng-untouched ng-valid ng-empty">
</div>
</div>
</div>
</form>
You can use ng-class to add class dynamically as the document says
The ngClass directive allows you to dynamically set CSS classes on an
HTML element by databinding an expression that represents all classes
to be added.
Reference
https://docs.angularjs.org/api/ng/directive/ngClass

Check in controller which input element has been modified

I need to check which input element has modified in update form.
<form name="utilizationForm" role="form" novalidate>
<div class="row" data-ng-repeat="i in [1,2,3,4]">
<div class="col-md-3">
<div asterick class="form-group" ng-class="{'form-group has-success': !error['resource_type'] && (submitted), 'form-group has-error': (error['resource_type']) && (submitted)}">
<label for="resourceType">Resource Type</label>
<input type="hidden" name="id" id="id" class="form-control" ng-model="data['id' + i]" value="">
<select name="resourceType" id="resourceType" ng-model="data['resource_type' + i]" class="form-control" ng-required="true" >
<option ng-repeat="option in resourceTypeJson" value="{{option}}">{{option}}</option>
</select>
<span class="er-block" ng-show="utilizationForm.resourceType.$touched && utilizationForm.resourceType.$error.required">Please provide Resource type.</span>
<span ng-show="error.resource_type1" class="er-block">{{error.resource_type1}}</span>
</div>
</div>
<div class="col-md-3">
<label for="efforts">Efforts (in hours)</label>
<input type="hidden" name="id" id="id" class="form-control" ng-model="data['id' + i]" value="">
<input type="text" test-change name="efforts" id="efforts" class="form-control" ng-model="data['efforts' + i]" value="">
</div>
</div>
<div class="text-right" ng-class="{'col-md-6 mt25': showCompletion}">
<button class="btn btn-primary" ng-disabled="utilizationForm.$invalid" ng-click="addUtilizationReport()">{{buttonText}}</button>
</div>
</form>
Now when I click on update button I need to check which input element has modified in update form in controller. Please help.
If you put the input in a form with a name attribute and then give the input a name attribute, you can also access the input's $dirty property.
<div ng-controller="MyController">
<form name="myForm">
<input type="text" name="first" ng-model="firstName">
<input type="text" name="last" ng-model="lastName">
</form>
</div>
app.controller('MyController', function($scope) {
// Here you have access to the inputs' `$dirty` property
console.log($scope.myForm.first.$dirty);
console.log($scope.myForm.last.$dirty);
});
You can use $scope.myForm.$dirty to see if any fields have changed, and the $dirty property on each input's property on the form to see if that input has changed. You can even iterate over the myForm object (non-input-field objects have keys prefixed with a $):
angular.forEach($scope.myForm, function(value, key) {
if(key[0] == '$') return;
console.log(key, value.$dirty)
});
Here is simplest example of using $watch in controller:
var app = angular.module('myApp', []);
app.controller('appCtrl', function($scope, $location) {
$scope.$watch('abc', function(newVal,oldVal) {
if(oldVal != newVal){
alert("value changed!");
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-app="myApp" ng-controller="appCtrl">
<input type="text" name="first" ng-model="abc">
</div>

Disable default form input error in angular js

How do I disable the input error message showing by default below the text input boxes.
Here is my form:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="${pageContext.request.contextPath}/js/Registratonvalidation.js"></script>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script>
angular.module('myApp', []).controller("numOnlyRegex", function ($scope)
{
$scope.numOnlyRegex = /^\d{1,6}$/;
$scope.cityArray = ["hyderabad", "secunderabad", "delhi", "mumbai"];
}
.controller('FormSubmitController', function($scope) {
$scope.submit = function($event)
{
if ($scope.myForm.$invalid)
{
$scope.myForm.$submitted = true;
$event.preventDefault();
}
}); </script>
<!--<script src="${pageContext.request.contextPath}/numOnlyRegex.js"></script>-->
<title>Registration Form</title>
</head>
<body>
<div class="container">
<div class="col-md-6 col-md-offset-3">
<div class="panel panel-login">
<div class="panel-body">
<div class="row">
<div class="col-lg-12">
<h2 class="text-muted">Registration form</h2>
<!--onSubmit="return validate()"-->
<div ng-app="myApp" ng-controller="FormSubmitController" >
<form name="myForm" action="RegistrationServlet.do" method="POST" >
First name:<input type="text" class="form-control input-sm" name="uname" ng-pattern="/^[a-zA-Z]{3,20}/" ng-model="uname" placeholder="First Name" required/>
<span style="color:red" ng-show="myForm.uname.$error.pattern">First name cannot be less than 3 letters with no digits</span>
<!--<p ng-show="myForm.uname.$invalid && !userForm.name.$pristine" class="help-block">Your name is required.</p>-->
<br/>
Last name:<input type="text" class="form-control input-sm" name="lname" ng-model="lname" name="uname" ng-pattern="/^[a-zA-]{3,20}/" required placeholder="Last Name"/>
<span style="color:red" ng-show="myForm.lname.$error.pattern">First name cannot be less than 3 letters with no digits</span><br/>
<p>Password:
<input type="password" class="form-control input-sm glyphicon glyphicon-ok" name="pwd" ng-minlength="3" ng-model="pwd" required placeholder="Password"/>
<span style="color:red" ng-show="myForm.pwd.$error.minlength">password cannot be less than 3 letters</span><br/>
Confirm Password:<input type="password" class="form-control input-sm glyphicon glyphicon-ok" name="pwd2" ng-minlength="3" ng-model="pwd2" required placeholder="Confirm Password"/><br/>
<span style="color:red" ng-show="myForm.pwd2.$error.minlength">password cannot be less than 3 letters</span><br/>
Gender: <input type="radio" name="female" ng-model="color" value="female" ng-required="!color"/>Female <input type="radio" name="male" ng-model="color" value="male" ng-required="!color"/>Male <br/><br/>
Mobile:<input type="text" class="form-control input-sm" name="mobile" ng-pattern="/^[7-9][0-9]{1,9}$/" ng-model="mobile" required placeholder="Mobile"/>
<span style="color:red" ng-show="myForm.mobile.$error.pattern">Please enter a valid mobile number</span><br/>
Email:<input type="email" class="form-control input-sm" name="email" ng-pattern="/\S+#\S+\.\S+/" ng-model="email" required placeholder="Email"/>
<span style="color:red" ng-show="myForm.email.$error.pattern">Invalid email address</span><br/>
Address:<textarea class="form-control input-sm" name="address" ng-model="address" required placeholder="Address"></textarea>
<span style="color:red" ng-show="myForm.address.$error.require == true">Address cannot be empty</span><br/>
Street:<input type="text" class="form-control input-sm" name="street" ng-model="street" required placeholder="Street"/>
Area:<input type="text" class="form-control input-sm" name="area" ng-model="area" required placeholder="Area"/><br/>
City: <select name="citySelection" ng-model="city" ng-options="city for city in cityArray" name='city' required>
<option value="">Select city</option>
</select>
<span ng-show="myForm.citySelection.$error.required"></span>
<br/><br/>
State: <input type="text" class="form-control input-sm" name="state" ng-model="state" required placeholder="State"/>
Country: <input type="text" class="form-control input-sm" name="country" ng-model="country" required placeholder="Country"/>
Pin:<input type="text" class="form-control input-sm" ng-pattern="numOnlyRegex" name="pin" ng-model="pin" required placeholder="Pin"/>
<span style="color:red" ng-show="myForm.pin.$error.pattern">Only six-digit number is allowed</span>
<!--<input type="Submit" class="form-control btn btn-success" ng-submit="submit($event)" value="Submit" />-->
<button type="submit" class="form-control btn btn-success" ng-click="submit($event)">Submit</button>
<!--ng-disabled="myForm.$invalid"-->
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
Link for the plunker
Try with this method:
function validateMethod() {
$scope.isValidated = true;
if($scope.uname == '') {
$scope.isValidated = false ;
}
//other custom validations
return $scope.isValidated;
}
MOdify the angular code as:
var valid = validateMethod();
if(valid)
{
$scope.submit = function($event)
{
if ($scope.myForm.$invalid)
{
$scope.myForm.$submitted = true;
$event.preventDefault();
}
});
}

How to disable the form submit when input fields are incorrect in angularjs

I have a form where I am checking for incorrect input with ng-pattern and showing error message on incorrect entry.
I want the form submit to be disabled when user tries to submit the form with incorrect values with out using ng-disabled option because required option of html is checking for empty text boxes on clicking submit button. How do I achieve this? Do I have to go for custom directive?
<%#page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script src="${pageContext.request.contextPath}/js/Registratonvalidation.js"></script>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script>
angular.module('myApp', []).controller("numOnlyRegex", function ($scope)
{
$scope.numOnlyRegex = /^\d{1,6}$/;
});
</script>
<!--<script src="${pageContext.request.contextPath}/numOnlyRegex.js"></script>-->
<title>Registration Form</title>
</head>
<body>
<div class="container">
<div class="col-md-6 col-md-offset-3">
<div class="panel panel-login">
<div class="panel-body">
<div class="row">
<div class="col-lg-12">
<h2 class="text-muted">Registration form</h2>
<!--onSubmit="return validate()"-->
<div ng-app="myApp" ng-controller="numOnlyRegex">
<form name="myForm" action="RegistrationServlet.do" method="POST" novalidate >
First name:<input type="text" class="form-control input-sm" name="uname" ng-pattern="/^[a-zA-Z]{3,20}/" ng-model="uname" placeholder="First Name" required/>
<span style="color:red" ng-show="myForm.uname.$error.pattern">First name cannot be less than 3 letters with no digits</span><br/>
Last name:<input type="text" class="form-control input-sm" name="lname" ng-model="lname" name="uname" ng-pattern="/^[a-zA-]{3,20}/" required placeholder="Last Name"/>
<span style="color:red" ng-show="myForm.lname.$error.pattern">First name cannot be less than 3 letters with no digits</span><br/>
<p>Password:
<input type="password" class="form-control input-sm glyphicon glyphicon-ok" name="pwd" ng-minlength="3" ng-model="pwd" required placeholder="Password"/>
<span style="color:red" ng-show="myForm.pwd.$error.minlength">password cannot be less than 3 letters</span><br/>
Confirm Password:<input type="password" class="form-control input-sm glyphicon glyphicon-ok" name="pwd2" ng-minlength="3" ng-model="pwd2" required placeholder="Confirm Password"/><br/>
<span style="color:red" ng-show="myForm.pwd2.$error.minlength">password cannot be less than 3 letters</span><br/>
Gender: <input type="radio" name="female" ng-model="color" value="female" ng-required="!color"/>Female <input type="radio" name="male" ng-model="color" value="male" ng-required="!color"/>Male <br/><br/>
Mobile:<input type="text" class="form-control input-sm" name="mobile" ng-pattern="/^[7-9][0-9]{1,9}$/" ng-model="mobile" required placeholder="Mobile"/>
<span style="color:red" ng-show="myForm.mobile.$error.pattern">Please enter a valid mobile number</span><br/>
Email:<input type="email" class="form-control input-sm" name="email" ng-pattern="/\S+#\S+\.\S+/" ng-model="email" required placeholder="Email"/>
<span style="color:red" ng-show="myForm.email.$error.pattern">Invalid email address</span><br/>
Address:<textarea class="form-control input-sm" name="address" ng-model="address" required placeholder="Address"></textarea>
<span style="color:red" ng-show="myForm.address.$error.require==true">Address cannot be empty</span><br/>
Street:<input type="text" class="form-control input-sm" name="street" ng-model="street" required placeholder="Street"/>
Area:<input type="text" class="form-control input-sm" name="area" ng-model="area" required placeholder="Area"/>
City: <select name="city" class="form-control" ng-model="city" required>
<option value="hyderabad">Hyderabad</option>
<option value="secunderabad">Secunderabad</option>
<option value="delhi">Delhi</option>
<option value="mumbai">Mumbai</option>
</select><br/>
State: <input type="text" class="form-control input-sm" name="state" ng-model="state" required placeholder="State"/>
Country: <input type="text" class="form-control input-sm" name="country" ng-model="country" required placeholder="Country"/>
Pin:<input type="text" class="form-control input-sm" ng-pattern="numOnlyRegex" name="pin" ng-model="pin" required placeholder="Pin"/>
<span style="color:red" ng-show="myForm.pin.$error.pattern">Only six-digit number is allowed</span>
<input type="Submit" class="form-control btn btn-success" value="Submit" />
<!--ng-disabled="myForm.$invalid"-->
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
This link will help explain how to disable a submit button until a form is valid.
You will need to add ng-disabled="FORMNAME.$invalid" attribute to your <input type="Submit" class="form-control btn btn-success" value="Submit" /> element (replace FORMNAME with the model name for your form data).
That should do it. Comment below with any other issues.
You appear to want all fields to be required, but that when users think they're ready for form submission, they are kindly notified if they have forgotten any required fields.
Normally this is achieved with ng-submit and something like:
<span ng-if="myForm.$submitted && myForm.formField.$error.required">Please enter information for 'formField'</span>
Here the users are allowed to click submit, but are then shown a message about the required field.
However, this is only works when no action (action="RegistrationServlet.do") is specified on the form. In your case, you need to intercept form submission. One way to do that is to capture the mouse click event to disable and update the form if there are form errors:
app.controller('MainCtrl', function($scope) {
$scope.submit = function($event) {
if ($scope.myForm.$invalid) {
$scope.myForm.$submitted = true;
$event.preventDefault();
}
}
<form name="myForm" action="action.do" method="Post" novalidate>
<input type="text" name="formField" ng-model="formField" required><br>
<span class="error" ng-if="myForm.$submitted && myForm.formField.$error.required">Please fill field above<br></span>
<button type="submit" ng-click="submit($event)">Submit</button>
</form>
See the plnkr here
What you need to do is using ng-Submit so that you can do validation when user click submit.
var app = angular.module('myApp',[]);
app.controller('numOnlyRegex',function($scope){
$scope.TestSubmit = function()
{
if($scope.myForm.$valid)
{
//normal submit
}
}
});
Updated base on you plunkr
http://plnkr.co/edit/FypBs8IiHmPKJYrsR1xJ?p=preview

Elements in $scope missing from form

I have this form (shown after page loads with Angular filled in data):
<div ng-controller="ItemsController">
<form name="Items" class="form-horizontal ng-dirty ng-valid-parse ng-valid ng-valid-required ng-submitted" ng-submit="submit()" _lpchecked="1">
<input ng-model="item._token" name="_token" type="hidden" value="gej20f0RMOJypfL5n93Mon3QL6PjrrgWgZ20RnGe" class="ng-pristine ng-untouched ng-valid">
<input ng-model="item.no_label" name="no_label" type="hidden" value="1" class="ng-pristine ng-untouched ng-valid">
<fieldset>
<legend>Add New Item</legend>
<div class="form-group">
<label class="col-md-2 control-label" for="sku">SKU</label>
<div class="col-md-3">
<input id="sku" name="sku" ng-model="item.sku" type="text" placeholder="Enter SKU" class="form-control input-md ng-dirty ng-valid-parse ng-valid ng-valid-required ng-touched" required="">
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="Name">Name</label>
<div class="col-md-5">
<input id="name" name="name" ng-model="item.name" type="text" placeholder="Optional name" class="form-control input-md ng-valid ng-dirty ng-valid-parse ng-touched">
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="add"></label>
<div class="col-md-4">
<button id="add" name="add" class="btn btn-success">
<i class="fa fa-plus"></i> Add
</button>
<button id="cancel" name="cancel" class="btn btn-danger">Cancel</button>
</div>
</div>
</fieldset>
</form>
</div>
And this controller:
myApp.controller('ItemsController', ['$scope', '$http', function ($scope, $http) {
$scope.item = {};
$scope.submit = function () {
if ($scope.validate()) {
$http.post('/items/store', $scope.item)
.success(function (data) {
toastr['success']('Added ' + $scope.item.sku + ' to list.', 'Success!');
$scope.Items.$setPristine();
oTable.ajax.reload();
}).error(function (data) {
if ('error' in data)
toastr['error']('ERROR: ' + data['error'], 'Error!');
else
toastr['error'](JSON.stringify(data), 'Error!');
});
}
};
$scope.validate = function () {
return $.trim($scope.item.sku) != '';
};
}]);
Everytime I submit this form, the data in $scope.item is missing item._token and item.no_label.
Why and how do I correct this?
ng-model is used for two-way data binding. Since you are using hidden input elements, which can not be modified by or shown to users, there is no reason using ng-model. The less two-way binding, the better Perf would be.
So the best way to fix this issue is that add _token and no_label value to $scope.item in controller.
$scope.item = {
_token: 'gej20f0RMOJypfL5n93Mon3QL6PjrrgWgZ20RnGe',
no_label: 1
};
If you must add these elements in View, use one-way binding in View
<input name="_token" type="hidden" value="{{:: item._token}}" class="ng-pristine ng-untouched ng-valid">
<input name="no_label" type="hidden" value="{{:: item.no_label}}" class="ng-pristine ng-untouched ng-valid">
Check this pr to know more about how Angular guys think about data binding on hidden elements.
Instead of using the value attribute try using ng-value:
<input ng-model="item._token" name="_token" type="hidden" ng-value="gej20f0RMOJypfL5n93Mon3QL6PjrrgWgZ20RnGe" class="ng-pristine ng-untouched ng-valid">
<input ng-model="item.no_label" name="no_label" type="hidden" ng-value="1" class="ng-pristine ng-untouched ng-valid">
Another option is updating item like this:
$scope.item = {
_token: 'gej20f0RMOJypfL5n93Mon3QL6PjrrgWgZ20RnGe',
no_label: 1
};

Resources