In the following example of my problem I have 2 fields needing to be validate.
Until all (2 in this case) fields are validated, the submit button should be disabled.
If both are validated it should be enabled.
My problem: The minute the first field is validated - the button is enabled, which is too early.
I understand (ot think that I do) that this occurs because of where I placed $("#submitBtn").attr("disabled",false);
Any hint of how to get it work would be greatly appreciated.
EDIT: For an example of a full registration form with the submit button enabled ONLY when all the form's elements are validated, see this.
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<style>
input[type="submit"]:disabled {
background-color: red; }
</style>
</head>
<body>
<div class="container mt-2">
<div class="row">
<div class="col-md-4 offset-md-4">
<form action="page2.php" id="myForm1" class="needs-validation" novalidate>
<div class="form-group">
<input type="text" class="form-control" pattern="^[a-z]{3,6}$" required autofocus>
<div class="valid-feedback">Valid</div>
<div class="invalid-feedback">a to z only (3 to 6 long)</div>
</div>
<div class="form-group">
<input type="text" class="form-control" pattern="^[a-z]{3,6}$" required>
<div class="valid-feedback">Valid</div>
<div class="invalid-feedback">a to z only (3 to 6 long)</div>
</div>
<div class="form-group">
<button id="submitBtn" type="submit" class="btn btn-primary submit-button" disabled>Submit</button>
</div>
</form>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script>
window.addEventListener('load', function() {
let currForm1 = document.getElementById('myForm1');
// Validate on input:
currForm1.querySelectorAll('.form-control').forEach(input => {
input.addEventListener(('input'), () => {
if (input.checkValidity()) {
input.classList.remove('is-invalid')
input.classList.add('is-valid');
$("#submitBtn").attr("disabled",false); <<<<======== ??????
} else {
input.classList.remove('is-valid')
input.classList.add('is-invalid');
}
});
});
// Validate on submit:
currForm1.addEventListener('submit', function(event) {
if (currForm1.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
currForm1.classList.add('was-validated');
}, false);
});
</script>
Inside your input event listener check if all the inputs have an is-valid class. If all your inputs have an is-valid class, turn off the disabled button.
currForm1.querySelectorAll('.form-control').forEach(input => {
input.addEventListener(('input'), () => {
if (input.checkValidity()) {
input.classList.remove('is-invalid')
input.classList.add('is-valid');
// $("#submitBtn").attr("disabled",false); <<<<======== ??????
} else {
input.classList.remove('is-valid')
input.classList.add('is-invalid');
}
var is_valid = $('.form-control').length === $('.form-control.is-valid').length;
$("#submitBtn").attr("disabled", !is_valid);
});
});
I don't know this is good approach or not and it also depend on your requirement if it fulfil your need so that's fine..
here i'm removing some line and adding some line
remove disable button code from first condition and added at the last
if(input.checkValidity() && index ===1) {
$("#submitBtn").attr("disabled", false);
}
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<style>
input[type="submit"]:disabled {
background-color: red; }
</style>
</head>
<body>
<div class="container mt-2">
<div class="row">
<div class="col-md-4 offset-md-4">
<form action="page2.php" id="myForm1" class="needs-validation" novalidate>
<div class="form-group">
<input type="text" class="form-control" pattern="^[a-z]{3,6}$" required autofocus>
<div class="valid-feedback">Valid</div>
<div class="invalid-feedback">a to z only (3 to 6 long)</div>
</div>
<div class="form-group">
<input type="text" class="form-control" pattern="^[a-z]{3,6}$" required>
<div class="valid-feedback">Valid</div>
<div class="invalid-feedback">a to z only (3 to 6 long)</div>
</div>
<div class="form-group">
<button id="submitBtn" type="submit" class="btn btn-primary submit-button" disabled>Submit</button>
</div>
</form>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
<script>
window.addEventListener('load', function() {
let currForm1 = document.getElementById('myForm1');
// Validate on input:
currForm1.querySelectorAll('.form-control').forEach((input, index) => {
input.addEventListener(('input'), () => {
if (input.checkValidity()) {
console.log(input.checkValidity());
input.classList.remove('is-invalid')
input.classList.add('is-valid');
} else {
input.classList.remove('is-valid')
input.classList.add('is-invalid');
}
if(input.checkValidity() && index ===1) {
$("#submitBtn").attr("disabled", false);
}
});
});
// Validate on submit:
currForm1.addEventListener('submit', function(event) {
if (currForm1.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
currForm1.classList.add('was-validated');
}, false);
});
</script>
</body>
</html>
We need to check if all the other inputs are also valid before assuming that we can just enable it
let currForm1 = document.getElementById('myForm1');
// Validate on input:
currForm1.querySelectorAll('.form-control').forEach(input => {
input.addEventListener(('input'), () => {
if (input.checkValidity()) {
/* IF IT PASSES WE NEED TO CHECK THE OTHER INPUTS */
/* STORE ALL THE INPUTS THAT PASS THE CHECKVALIDITY */
let allValid = currForm1.querySelectorAll('.form-control').filter(input =>
{ return input.checkValidity() })
/* WE CAN NOW UPDATE THE SUBMIT BASED ON THE NUMBER OF VALID
INPUTS WE HAVE */
$("#submitBtn").attr("disabled", allValid.length === currForm1.querySelectorAll('.form-control').length);
input.classList.remove('is-invalid')
input.classList.add('is-valid');
} else {
/* IF IT FAILS WE DONT NEED TO CHECK WE WANT THE VALIDATOR AS FALSE */
$("#submitBtn").attr("disabled", true);
input.classList.remove('is-valid')
input.classList.add('is-invalid');
}
});
});
/* FINALLY WE CAN UPDATE THE SUBMIT, BASED ON OUR VARIABLE */
$("#submitBtn").attr("disabled", validatorForSubmit );
Related
I can't get my form to validate despite having the script both on the page and in my boilerplate layout. I have tried moving the tags around to different places but the server-side validation is the only part working.. the form won't run the client side validation.
<% layout('layouts/boilerplate') %>
<div class="row">
<h1 class="text-center">Create Artist Profile</h1>
<div class="col-6 offset-3">
<form action="/artists/new" method="POST" novalidate class="validated-form" enctype="multipart/form-data">
<div class="mb-3">
<label class="form-label" for="email">Email</label>
<input class="form-control" type="email" id="email" name="email" placeholder="name#domain.com" required>
<div class="valid-feedback">
Looks good!
</div>
</div>
<div class="mb-3">
<label for="formFile" class="form-label">Upload band photo</label>
<input class="form-control" type="file" id="image" name="image" multiple="false">
</div>
<div class="mb-3">
<button class="btn btn-success">Create Profile</button>
</div>
All artists
</form>
</div>
</div>
Here's the script tag from the body of my layouts/boilerplate.ejs
<script>
(function () {
'use strict'
bsCustomFileInput.init()
// Fetch all the forms we want to apply custom Bootstrap validation styles to
const forms = document.querySelectorAll('.validated-form')
// Loop over them and prevent submission
Array.from(forms)
.forEach(function (form) {
form.addEventListener('submit', function (event) {
if (!form.checkValidity()) {
event.preventDefault()
event.stopPropagation()
}
form.classList.add('was-validated')
}, false)
})
})
</script>
Any ideas what I'm doing wrong with this form?
have you tried changing the form class to "needs-validation"?
also try this code
(function() {
'use strict';
window.addEventListener('load', function() {
var forms = document.querySelectorAll('.validated-form')
var validation = Array.prototype.filter.call(forms, function(form) {
form.addEventListener('submit', function(event) {
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false);
});
}, false);
})();
I'm using setCustomValidity function to check if the new password and the repeat password are equals but , I debugged the code and the comparisson its correct but the error message its not shown and the form post request its done
<form action="/register" method="post" onsubmit="check_new_password()">
<div class="form-group">
and the javascript
function check_new_password(){
var new_pass = $('#new-password').val();
var repeated_pass = $('#repeat-password').val();
if(new_pass != repeated_pass){
$('#repeat-password')[0].setCustomValidity('Password are not equals');
}else{
$('#repeat-password')[0].setCustomValidity('');
}
You need to add the return statement in the onsubmit attribute, like this:
onsubmit="return check_new_password();"
So, the check_new_password() function needs to return a boolean according the validation.
Don't forget call the .reportValidity(); method because you're using HTMLObjectElement.setCustomValidity() method.
Additionally, you should add oninput="setCustomValidity('');" on the inputs fields to force to update its state.
See in this example:
function check_new_password() {
var new_pass = $('#new-password').val();
var repeated_pass = $('#repeat-password').val();
if (new_pass != repeated_pass) {
$('#repeat-password')[0].setCustomValidity('Password are not equals.');
$('#repeat-password')[0].reportValidity();
return false;
} else {
$('#repeat-password')[0].setCustomValidity('');
return true;
}
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
<form action="/register" method="post" onsubmit="return check_new_password();">
<div class="form-group">
<label for="new-password">Password:</label>
<input id="new-password" class="form-control" type="password" oninput="setCustomValidity('');" />
</div>
<div class="form-group">
<label for="repeat-password">Repeat Password:</label>
<input id="repeat-password" class="form-control" type="password" oninput="setCustomValidity('');" />
</div>
<div>
<button class="btn btn-xs btn-primary" type="submit">Send</button>
</div>
</form>
</div>
I am trying to add a Bootstrap validation in a form. My expected results is:
When the form is submitted, if "First name" field is empty, the "Please enter a name" message should be displayed below the field, otherwise "Looks good" should be displayed.
I tried it by adding and removing "d-none" class in the javascript, but the problem is "Looks good" is disappearing but "Please enter a name" is not displaying.
// Example starter JavaScript for disabling form submissions if there are invalid fields
(function () {
'use strict';
window.addEventListener('load', function () {
// Fetch all the forms we want to apply custom Bootstrap validation styles to
var forms = document.getElementsByClassName('needs-validation');
// Loop over them and prevent submission
var validation = Array.prototype.filter.call(forms, function (form) {
form.addEventListener('submit', function (event) {
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
var invalidOptions = document.querySelectorAll(".form-control:invalid");
invalidOptions.forEach(function (element) {
element.parentNode.childNodes.forEach(function (node) {
if (node.className == 'valid-feedback') {
node.classList.add('d-none');
}
});
});
var validOptions = document.querySelectorAll(".form-control:valid");
invalidOptions.forEach(function (element) {
element.parentNode.childNodes.forEach(function (node) {
if (node.className == 'invalid-feedback') {
node.classList.remove('d-none');
}
});
});
}
form.classList.add('was-validated');
}, false);
});
}, false);
})();
<!DOCTYPE html>
<html lang="en">
<head>
<title>Bootstrap Example</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</head>
<body>
<form class="needs-validation" novalidate>
<div class="form-row">
<div class="col-md-4 mb-3">
<label for="validationServer01">First name</label>
<input type="text" class="form-control is-valid" id="validationServer01" placeholder="First name" value="Mark"
required>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback d-none">Please enter a name</div>
</div>
</div>
<div class="form-row">
<div class="col-md-4 mb-3">
<button class="btn btn-primary" type="submit">Submit form</button>
</div>
</div>
</form>
</body>
</html>
Your js code is Bootstrap will manage the showing & hiding of the valid-feedback and invalid-feedback depending on whether the content is valid. By manually adding d-none to the invalid-feedback, it is affecting this behaviour. Simply remove d-none from the classes and it works:
<label for="validationServer01">First name</label>
<input type="text" class="form-control is-valid"
id="validationServer01" placeholder="First name" value="Mark"
required>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">Please enter a name</div> <!-- REMOVE d-none FROM HERE -->
Now, when you submit the form, if the name is empty it will show your "Please enter a name" message.
Working Example:
// Example starter JavaScript for disabling form submissions if there are invalid fields
(function () {
'use strict';
window.addEventListener('load', function () {
// Fetch all the forms we want to apply custom Bootstrap validation styles to
var forms = document.getElementsByClassName('needs-validation');
// Loop over them and prevent submission
var validation = Array.prototype.filter.call(forms, function (form) {
form.addEventListener('submit', function (event) {
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
var invalidOptions = document.querySelectorAll(".form-control:invalid");
invalidOptions.forEach(function (element) {
element.parentNode.childNodes.forEach(function (node) {
if (node.className == 'valid-feedback') {
node.classList.add('d-none');
}
});
});
var validOptions = document.querySelectorAll(".form-control:valid");
invalidOptions.forEach(function (element) {
element.parentNode.childNodes.forEach(function (node) {
if (node.className == 'invalid-feedback') {
node.classList.remove('d-none');
}
});
});
}
form.classList.add('was-validated');
}, false);
});
}, false);
})();
<!DOCTYPE html>
<html lang="en">
<head>
<title>Bootstrap Example</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</head>
<body>
<form class="needs-validation" novalidate>
<div class="form-row">
<div class="col-md-4 mb-3">
<label for="validationServer01">First name</label>
<input type="text" class="form-control is-valid" id="validationServer01" placeholder="First name" value="Mark"
required>
<div class="valid-feedback">Looks good!</div>
<div class="invalid-feedback">Please enter a name</div>
</div>
</div>
<div class="form-row">
<div class="col-md-4 mb-3">
<button class="btn btn-primary" type="submit">Submit form</button>
</div>
</div>
</form>
</body>
</html>
I have form in the system that has a field that should be validated before user submits the form. The first field on the form is 'Type' input field, and second is 'User ID' input field. Here is working example of my current code:
var data = {
93169: "John Rives",
33442: "Mike Cook",
70354: "Tammy Bull",
22078: "Nick Adams"
};
$("#user_id").on("keyup", function() {
var inputFld = $(this),
msgFld = $(this).closest("div").find(".invalid-feedback");
if (!inputFld.val().length) {
inputFld.removeClass("is-invalid").val("");
msgFld.text("");
$("#save").prop("disabled", false);
}
});
$("#user_type").on("change", function() {
var inputVal = $(this).val();
if (inputVal) {
$("#user_id").prop("disabled", false);
} else {
$("#user_id").prop("disabled", true);
}
// Every time on change reset affiliate field and remove the calss.
$("#user_id").removeClass("is-invalid").val("");
$("#user_name").text("N/A");
$("#save").prop("disabled", false);
});
$("#search_user").on("click", function() {
var inputFld = $(this).parent().parent().children("input"),
msgFld = inputFld.closest("div").find(".invalid-feedback"),
typeID = $("#user_type").val(),
saveBtn = $("#save"),
userID = inputFld.val(),
regex = /^([0-9]{1,5})$/;
if (userID) {
if (regex.test(userID) === false) {
saveBtn.prop("disabled", true);
inputFld.addClass("is-invalid");
msgFld.text("User ID has to be numeric 1-5 digits long.");
$("#user_name").text("N/A");
} else {
var userName = data[userID];
populateUser(userName, inputFld, msgFld, saveBtn);
}
} else {
inputFld.removeClass('is-invalid');
$('#user_name').text('N/A');
}
});
function populateUser(userName, inputFld, msgFld, saveBtn) {
if (!userName) {
saveBtn.prop('disabled', true);
inputFld.addClass('is-invalid');
msgFld.text("User doesn't exist.");
$("#user_name").text("N/A");
} else {
inputFld.removeClass("is-invalid");
$("#user_name").text(userName);
}
}
#search_user {
border-top-right-radius: 0.25rem !important;
border-bottom-right-radius: 0.25rem !important;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<script src="https://use.fontawesome.com/a6e6aa2b6e.js"></script>
<div class="container">
<form name="my_frm" id="my_frm" autocomplete="off">
<div class="form-row">
<div class="form-group col-4">
<label>User Type:</label>
<select class="custom-select browser-default" name="user_type" id="user_type" required>
<option value="">--Select Type--</option>
<option value="1">Director</option>
<option value="2">Project Manager</option>
<option value="3">Assistant Manager</option>
</select>
</div>
<div class="form-group col-4">
<label class="control-label" for="user_id">User ID:</label>
<div class="input-group">
<div class="input-group addon">
<input class="form-control" type="text" name="user_id" id="user_id" maxlength="5" placeholder="Enter User ID" disabled>
<div class="input-group-append">
<button class="btn btn-secondary" type="button" name="search_user" id="search_user"><i class="fa fa-search"></i></button>
</div>
<div class="invalid-feedback"></div>
</div>
</div>
</div>
<div class="form-group col-4">
<p>User Name:</p>
<p id="user_name">N/A</p>
</div>
</div>
<div class="row">
<div class="col-12 text-center">
<button class="btn btn-outline-secondary" type="button" name="save" id="save">Save</button>
</div>
</div>
</form>
</div>
In the example above you will be able to see function with some examples. One thing that I'm concerned about is what if user enters user ID and doesn't click on search button? In that case user is still able to submit the form before user ID is validated. I'm wondering if there is a way to prevent form submission/ disable Save button until User ID has value in the field and that value is not validated. If someone can help me fix that or if you have any suggestions please let me know. I'm also open to hear if you have better ways to achieve this validation.
You can add a disabled attribute (or class) to your save button, then after the successfull validation, remove it.
In the callback for the button, you will check if the button is disabled or not
$("#save").click(function() {
if ($(this).hasClass("disabled")) {
console.log("wait for validation!")
return;
}
//do stuff
});
$("#val").click(function() {
$("#save").removeClass("disabled");
});
.disabled {
opacity: .7;
cursor: not-allowed;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="btn btn-outline-secondary disabled" type="button" name="save" id="save">Save</button>
<button class="btn btn-outline-secondary" type="button" name="val" id="val">Validate</button>
Usually I use formName.inputName.$invalid to show error message input like this:
<input name="myInput" minlength="3" />
<span ng-show="myForm.myInput.$invalid">too short</span>
that won't be a problem.
But when I tried to validate checkbox,it seems difficult, there are the snippet at the end.
I want the effect that user should at least check one checkbox ,or you got the warning message.
How can I do that in a simple way at best?
// app.js
var formApp = angular.module('formApp', [])
.controller('formController', function($scope) {
// we will store our form data in this object
$scope.formData = {};
$scope.formData.favoriteColors = [{
'id':'1',
'name':'red'
},{
'id':'2',
'name':'green'
},{
'id':'3',
'name':'blue'
}];
$scope.cList = [];
$scope.checkList = function(index){
if($scope.myForm.favoriteColors.$pristine){
$scope.cList.push($scope.formData.favoriteColors[index]);
}
else{
angular.forEach($scope.formData.favoriteColors,function(value,key){
if(value.checked){
$scope.cList.push(value.id);
}
});
}
console.log('cList:%o',$scope.cList);
};
});
<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
<!-- CSS -->
<!-- load up bootstrap and add some spacing -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.20/angular.min.js"></script>
<link href="http://cdn.bootcss.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet"/>
<style>
body { padding-top:50px; }
form { margin-bottom:50px; }
</style>
<!-- JS -->
<!-- load up angular and our custom script -->
<script src="lib/angular/angular.min.js"></script>
<script src="app.js"></script>
</head>
<!-- apply our angular app and controller -->
<body ng-app="formApp" ng-controller="formController">
<div class="col-xs-12 col-sm-10 col-sm-offset-1">
<h2>Angular Checkboxes and Radio Buttons</h2>
<form name="myForm">
<!-- NAME INPUT -->
<div class="form-group">
<label>Name</label>
<input type="text" class="form-control" name="name" ng-model="formData.name">
</div>
<!-- MULTIPLE CHECKBOXES -->
<label>Favorite Colors</label>
<div class="form-group">
<label class="checkbox-inline" ng-repeat="color in formData.favoriteColors">
<input type="checkbox" name="favoriteColors" ng-model="color.checked" ng-click="checkList($index)" required>{{color.name}}
</label>
<span class="danger" ng-show="myForm.favoriteColors.$invalid">Please check one color at least</span>
</div>
<!-- SUBMIT BUTTON (DOESNT DO ANYTHING) -->
<button type="submit" class="btn btn-danger btn-lg">Send Away!</button>
</form>
<!-- SHOW OFF OUR FORMDATA OBJECT -->
<h2>Sample Form Object</h2>
<pre>
dirty:{{ myForm.favoriteColors.$dirty }}
pristine:{{ myForm.favoriteColors.$pristine }}
valid:{{ myForm.favoriteColors.$valid }}
invalid:{{ myForm.favoriteColors.$invalid }}
error:{{ myForm.favoriteColors.$error }}
</pre>
</div>
</body>
</html>
Here is the live demo:http://jsbin.com/yigujoporu/1/
I use a count funtcion to update the number of checked checkbox.
Here is the live demo:http://jsbin.com/wowipi/4/edit?js,output
You can custom validation by another way
First, in your controller
$scope.cList = [];
$scope.checked = false;
$scope.checkList = function(index){
if($scope.myForm.favoriteColors.$pristine){
$scope.cList.push($scope.formData.favoriteColors[index]);
}
else{
if($scope.formData.favoriteColors[index].checked == true){
//checked
$scope.cList.push($scope.formData.favoriteColors[index]);
}else{
//uncheck
angular.forEach($scope.cList, function(value,key){
if($scope.formData.favoriteColors[index].id == value.id){
//remove it
$scope.cList.splice(key,1);
}
}
}
console.log('cList:%o',$scope.cList);
//new change
if($scope.cList.length >0) {
$scope.checked = true;
}else{
$scope.checked = false;
}
};
In your view
<div class="form-group">
<label class="checkbox-inline" ng-repeat="color in formData.favoriteColors">
<input type="checkbox" name="favoriteColors" ng-model="formData.favoriteColors[$index].checked" ng-click="checkList($index)" required>{{color.name}}
</label>
<span class="danger" ng-show="!checked">Please check one color at least</span>
</div>