I want to make use of Bootstrap 4's form validation. From what I read you can invalidate a field by adding class 'is-invalid' - this works, but when I want to check the form validity using method checkValidity() it still says the form is VALID which is not what I expected. I was hoping of making use of the native bootstrap 4 functionality and not use plugins such as jquery validator etc.
$('#submit_button').on('click', function(e){
var forms = document.getElementsByClassName('needs-validation');
var validation = Array.prototype.filter.call(forms, function(form) {
if (form.checkValidity() === false) {
console.log("form is INVALID")
event.preventDefault();
event.stopPropagation();
} else {
console.log("form is VALID")
}
// form.classList.add('was-validated');
});
})
<link href="https://cdnjs.cloudflare.com/ajax/libs/jquery.bootstrapvalidator/0.5.3/css/bootstrapValidator.min.css" rel="stylesheet"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<head>
</head>
<body>
<form class="needs-validation" id="my_form">
<div class="form-group">
<div class="form-check">
<label for="taskname_l">Task Name</label>
<div class="form-inline">
<input type="text" class="form-control task_form is-invalid" id="taskname_in" name="taskname_in">
</div>
</div>
</div>
<button class="btn btn-primary" type="button" id="submit_button">Submit form</button>
</form>
</body>
Option 1:
Using JQUERY you can use the .val() function
To get the value of the input field with id "taskname_in" use this code
$('#taskname_in').val()
Option 1 snippet:
$('#submit_button').on('click', function(e) {
var forms = document.getElementsByClassName('needs-validation');
var validation = Array.prototype.filter.call(forms, function(form) {
if ($('#taskname_in').val() == '') {
console.log("form is INVALID")
event.preventDefault();
event.stopPropagation();
} else {
console.log("form is VALID")
}
// form.classList.add('was-validated');
});
})
<link href="https://cdnjs.cloudflare.com/ajax/libs/jquery.bootstrapvalidator/0.5.3/css/bootstrapValidator.min.css" rel="stylesheet" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<head>
</head>
<body>
<form class="needs-validation" id="my_form">
<div class="form-group">
<div class="form-check">
<label for="taskname_l">Task Name</label>
<div class="form-inline">
<input type="text" class="form-control task_form" id="taskname_in" name="taskname_in">
</div>
</div>
</div>
<button class="btn btn-primary" type="button" id="submit_button">Submit form</button>
</form>
</body>
Option 2:
Using form validator to check all input-fields at once.
Option 2 snippet:
(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();
}
form.classList.add('was-validated');
}, false);
});
}, false);
})();
<link href="https://cdnjs.cloudflare.com/ajax/libs/jquery.bootstrapvalidator/0.5.3/css/bootstrapValidator.min.css" rel="stylesheet" />
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form class="needs-validation" novalidate>
<div class="form-row">
<div class="col-md-4 mb-3">
<label for="validationCustom01">First name</label>
<input type="text" class="form-control" id="validationCustom01" placeholder="First name" value="Mark" required>
<div class="valid-feedback">Looks good!</div>
</div>
<div class="col-md-4 mb-3">
<label for="validationCustom02">Last name</label>
<input type="text" class="form-control" id="validationCustom02" placeholder="Last name" value="" required>
<div class="valid-feedback">Looks good!</div>
</div>
</div>
<button class="btn btn-primary btn-sm" type="submit">Submit form</button>
</form>
'is-invalid' does not make that particular field an invalid. it just applies CSS to look as it's invalid.
Result of HTMLElement.checkValidity() depends on its Constraint.
Suppose, you add field with 'required' constrain and you run checkValidity() on the form or field while it's empty, you will receive response as false, which means that a form or field is not valid.
In your case, just add required in your input field and you will receive response as invalid if you submit form while field is empty.
If you have the default Bootstrap validation code for the required fields:
$(".needs-validation").submit(function() {
var form = $(this);
if (form[0].checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
form.addClass('was-validated');
});
You would just need to add another validation for example on input and use the setCustomValidity. For example if you want to check for equal values on password and confirm password:
if ($('form input[name="confirm_password"').length > 0) {
$('input[name="confirm_password"').on('change paste keyup', function() {
var password = $(this).closest('form').find('input[name="password"').val();
if($(this).val() !== password){
this.setCustomValidity('Passwords must match');
} else {
this.setCustomValidity('');
}
});
};
If you have an invalid-feedback message next to the input element it will show that message instead of the one you set here.
Related
I'm having some troubles with Bootstrap 5 and JQuery Validator with custom class.
Seems it works separately from Bootstrap.
In this method for checking hex validity (optional) the .was-validated form class generates problems.
jQuery.validator.addMethod("isvalidhex", function(value, element) {
return this.optional(element) || value.match(/^#[a-f0-9]{6}$/i) !== null;
}, "Must be a valid hex");
Here my code
<script src="https://code.jquery.com/jquery-3.6.1.js" integrity="sha256-3zlB5s2uwoUzrXK3BT7AX3FyvojsraNFxCc2vC/7pNI=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery-validation#1.19.5/dist/jquery.validate.js"></script>
<script src="https://cdn.jsdelivr.net/npm/jquery-validation#1.19.5/dist/additional-methods.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.2.1/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
<style>form * { text-align:center; }</style>
<form method="POST" class="needs-validation" id="formAA" novalidate="novalidate">
<div class="mb-3">
<label for="a" class="form-label">A</label>
<input type="text" class="form-control form-control-lg text-center" id="a" name="a" maxlength="100" required="">
</div>
<div class="divdropdowncolor mb-3 text-center">
<label for="selectcolor" class="form-label">B</label><br>
<input class="form-control form-control-lg" type="color" id="selectcolor" name="selectcolor" value="#0AF000" style="display:inline-block; width:48%; vertical-align: middle; float:left;">
<input type="text" class="form-control form-control-lg text-center error" id="selectcolorB" name="selectcolorB" placeholder="#FFFFFF" maxlength="7" style="display:inline-block; width:48%; vertical-align: middle; float:right;" col="7" aria-invalid="true">
</div>
<div class="mb-3" style="clear:both;"></div>
<button type="submit" class="btn btn-primary form-control-lg" style="width:100%;">Submit</button>
</form>
<!-- scripts -->
<script>
function isValidColor(str) { return str.match(/^#[a-f0-9]{6}$/i) !== null; }
$(document).ready(function() {
$('#selectcolorB').val($('#selectcolor').val());
});
$('#selectcolor').on('change', function (event) { $('#selectcolorB').val($('#selectcolor').val()); });
$('#selectcolorB').on('change', function (event) { if( isValidColor($('#selectcolorB').val()) ) { $('#selectcolor').val($('#selectcolorB').val()); } });
</script>
<script>
jQuery.validator.setDefaults({
debug: true,
success: "valid"
});
jQuery.validator.addMethod("isvalidhex", function(value, element) {
return this.optional(element) || value.match(/^#[a-f0-9]{6}$/i) !== null;
}, "Must be a valid hex");
$('#formAA').validate({
rules: {
selectcolorB : { isvalidhex : true },
bgcolor : { isvalidhex : true }
},
submitHandler: function(form, e) {
console.log('The form is valid and would have been submitted successfully');
}
});
</script>
<script>
(function () {
'use strict'
var forms = document.querySelectorAll('.needs-validation')
// Loop over them and prevent submission
Array.prototype.slice.call(forms)
.forEach(function (form) {
form.addEventListener('submit', function (event) {
if (!form.checkValidity()) {
//form.classList.remove('was-validated')
event.preventDefault()
event.stopPropagation()
}
form.classList.add('was-validated')
}, false)
})
})()
</script>
It's more complicated said than done.
So go use fiddle
https://jsfiddle.net/qmsjo3L7/
Insert in the second input a wrong hex, like (wekdne).
You got the error Must be a valid hex.
If you click over the submit button you can see that the errors are recognized
1) This field is required.
2) Must be a valid hex
but the inputs colors are red for the normal method (input a) and green for the custom method.
Also, if you edit the inputs, the custom method works when the input is changed (keyup or keydown, I don't know) but the normal method works only on submit.
There's someone more able than me that can solve this?
Click on submit
The last <script> block adds an additional submithandler which is causing odd results. Remove that and things immediately improve.
Bootstrap usage is demonstrated at https://github.com/jquery-validation/jquery-validation/blob/master/demo/bootstrap/index-bs4.html, and live demo available at https://jqueryvalidation.org/files/demo/bootstrap/index.html
Implement the errorElement, errorPlacement, highlight and unhighlight directives shown in the above demo and it works as you expect:
https://jsfiddle.net/bytestream/dekzfxns/2/
I found this on Bootstrap to use Bootstrap form validation. Why is the example in plain JavaScript instead of jQuery when the rest of Bootstrap scripts are in jQuery?
How can this be done with jQuery?
https://getbootstrap.com/docs/4.0/components/forms/#validation
<script>
// 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();
}
form.classList.add('was-validated');
}, false);
});
}, false);
})();
</script>
use Jquery Validation : https://jqueryvalidation.org/documentation/
$(document).ready(function(){
$('#contact-form').validate({
rules: {
'checkbox': {
required: true
}
},
highlight: function (input) {
$(input).addClass('is-invalid');
},
unhighlight: function (input) {
$(input).removeClass('is-invalid');
},
errorPlacement: function (error, element) {
$(element).next().append(error);
}
});
});
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/jquery-validation#1.17.0/dist/jquery.validate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js"></script>
<form id="contact-form" method="POST" action="/contact">
<div class="form-group">
<input type="text" class="form-control" name="name" placeholder="Name" id="name" class="form-control" autocomplete='name' value="" required>
<div class="invalid-feedback"></div>
</div>
<div class="form-group">
<input type="email" class="form-control" name="email" placeholder="Email" id="email" class="form-control" autocomplete='email' value="" required>
<div class="invalid-feedback"></div>
</div>
<div class="form-group">
<input type="text" class="form-control" name="phone" placeholder="Phone" id="phone" class="form-control" autocomplete='tel' value="" required>
<div class="invalid-feedback"></div>
</div>
<div class="form-group">
<textarea placeholder="Message" class="form-control" name="message" rows="5" class="form-control" required></textarea>
<div class="invalid-feedback"></div>
</div>
<div class="container-contact-form-btn">
<button class="btn btn-primary" type="submit">
Send Now
</button>
</div>
</form>
$(document).ready(function(){
$('.needs-validation').on('submit', function(e) {
if (!this.checkValidity()) {
e.preventDefault();
e.stopPropagation();
}
$(this).addClass('was-validated');
});
});
This example was most likely written in JS as that's what the author of the Bootstrap documentation was most comfortable with. You can convert it to jQuery like this:
(function() {
'use strict';
$(window).on('load', function() {
$('.needs-validation').on('submit', function(e) {
if (!this.checkValidity()) {
e.preventDefault();
e.stopPropagation();
}
$(this).addClass('was-validated');
});
});
})();
I have function that will be triggered on blur and send ajax request to check if username already exist in database. So far function works fine but I found one problem when user tries to update already saved username. Here is example of my code:
var usernames = ["jcook","mjones","kruffy"];
$(".check-account").focus(function() {
var submitBtn = $(this).closest("form").find(":submit");
submitBtn.prop("disabled", true); //Disable submit button on field focus.
$(this).attr('data-prev', $(this).val()); // Save current value in data attribute as data-prev.
if(!$(this).data("original")){
$(this).data("original",$(this).val());
}
}).blur(function() {
var fldObj = $(this),
submitBtn = $(this).closest("form").find(":submit");
if (fldObj.val() !== fldObj.data('prev') && fldObj.val() !== fldObj.data("original")) {
if ($.inArray(fldObj.val(), usernames) === -1) {
fldObj.data("original","");
fldObj[0].setCustomValidity("");
} else {
fldObj[0].setCustomValidity("User name already exist.");
}
submitBtn.prop("disabled", false);
} else {
fldObj[0].setCustomValidity("");
submitBtn.prop("disabled", false);
}
});
<script language="javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script language="javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<form name="frmSave" id="frmSave">
<input type="hidden" class="form-control" name="frm_recordid" id="frm_recordid">
<div class="form-group required">
<label class="control-label" for="username"><span class="label label-default">UserName:</span></label>
<input type="text" class="form-control check-account is-user" name="frm_username" id="frm_username" maxlength="50" required>
</div>
<div class="row">
<div class="form-group col-xs-12 col-sm-12 col-md-1 col-lg-1">
<button type="submit" name="frm_submit" id="frm_submit" class="btn btn-primary">Submit</button>
</div>
<div class="form-group col-xs-12 col-sm-12 col-md-11 col-lg-11">
<div id="frm_message" class="alert"></div>
</div>
</div>
</form>
If you run my code example above you will see that my function will catch username if already exist. The problem that I have is when I try to edit data. Let's say I open form and user name will have value jcook. Then I try to enter different username for example mjones. If I try to submit form I will get message Username already exist!. Then if I try to put jcook again my code will trigger same message even I just try to put the same value that was already in the field for that record. I'm wondering how to avoid function trigger in this case if username was already saved for that record?
I am trying to figure out why jquery validation does not stop my form from being submitted? When the submit button is pressed the form posts correctly but seems to ignore the validation error (This field is required) even if the input field is left blank.
The form
$(document).ready(function() {
$("#message").hide();
//Define your validation rules.
$(function() {
$("#myform").validate({
});
$("#submitButtonId").on("click", function(e) {
var formdata = $("#myform").serialize();
//Post form data
$.post('php_includes/simple_insert.php', formdata, function(data) {
//Process post response
$("#message").html(data);
$("#message").fadeIn(500);
$("#message").fadeOut(500);
});
//Reset Form
$('#myform')[0].reset();
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.15.0/jquery.validate.min.js"></script>
<form class="form-inline" action="" id="myform" method="post">
<!-- Text input-->
<div class="form-group">
<label class="col-md-4 control-label" for="bill_cost"></label>
<div class="col-md-8">
<input id="bill_cost" name="bill_cost" type="text" placeholder="Bill Cost" class="form-control input-lg" required>
</div>
</div>
<!-- Button -->
<div class="form-group">
<label class="col-md-4 control-label" for="submit1"></label>
<div class="col-md-4">
<button type="submit" id="submitButtonId" name="submit1" class="btn btn-primary btn-xl">Submit</button>
</div>
</div>
</form>
Try this, use submitHandler to do other things for a valid form:
$("#myform").validate({
submitHandler : function() {
var formdata = $("#myform").serialize();
//Post form data
$.post('php_includes/simple_insert.php', formdata, function(data){
//Process post response
$("#message").html(data);
$("#message").fadeIn(500);
$("#message").fadeOut(500);
});
//Reset Form
$('#myform')[0].reset();
}
});
Remove a Required tag in bill cost text box.then you check the validation is ignored
I want to create a stripe.js form, first the data should be validated client-side then submitted to stripe.js to get token. Here is my full source code:
<!DOCTYPE html><html>
<head>
<?php
print_r($_POST);
?>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
<script type="text/javascript" src="jquery.payment.js"></script>
<style type="text/css" media="screen">
.has-error input {
border-width: 2px;
}
.validation.text-danger:after {
content: 'Validation failed';
}
.validation.text-success:after {
content: 'Validation passed';
}
</style>
<script type="text/javascript">
jQuery(function($) {
$('[data-numeric]').payment('restrictNumeric');
$('.cc-number').payment('formatCardNumber');
$('.cc-exp').payment('formatCardExpiry');
$('.cc-cvc').payment('formatCardCVC');
$.fn.toggleInputError = function(erred) {
this.parent('.form-group').toggleClass('has-error', erred);
return this;
};
$('button[type="submit"]').click(function(e){
e.preventDefault();
var cardType = $.payment.cardType($('.cc-number').val());
$('.cc-number').toggleInputError(!$.payment.validateCardNumber($('.cc-number').val()));
$('.cc-exp').toggleInputError(!$.payment.validateCardExpiry($('.cc-exp').payment('cardExpiryVal')));
$('.cc-cvc').toggleInputError(!$.payment.validateCardCVC($('.cc-cvc').val(), cardType));
$('.cc-brand').text(cardType);
$('.validation').removeClass('text-danger text-success');
if ($('.has-error').length) { $('.validation').addClass('text-danger') } else { $('form').submit(); }
});
});
Stripe.setPublishableKey('pk_test_***');
jQuery(function($) {
$('#payment-form').submit(function(event) {
var $form = $(this);
// Disable the submit button to prevent repeated clicks
$form.find('button').prop('disabled', true);
Stripe.card.createToken($form, stripeResponseHandler);
// Prevent the form from submitting with the default action
return false;
});
});
function stripeResponseHandler(status, response) {
var $form = $('#payment-form');
if (response.error) {
// Show the errors on the form
$form.find('.payment-errors').text(response.error.message);
$form.find('button').prop('disabled', false);
} else {
// response contains id and card, which contains additional card details
var token = response.id;
// Insert the token into the form so it gets submitted to the server
$form.append($('<input type="hidden" name="stripeToken" />').val(token));
// and submit
$form.get(0).submit();
}
};
</script>
</head>
<body>
<div class="container">
<form action="" method="post" id="payment-form" novalidate autocomplete="on">
<span class="payment-errors"></span>
<div class="form-group">
<label for="cc-number" class="control-label">Card number:<small class="text-muted">[<span class="cc-brand"></span>]</small></label>
<input id="cc-number" data-stripe="number" type="tel" class="input-lg form-control cc-number" autocomplete="cc-number" placeholder="•••• •••• •••• ••••" required class="col-md-2">
</div>
<div class="form-group">
<label for="cc-exp" class="control-label">Card expiry:</label>
<input id="cc-exp" type="tel" class="input-lg form-control cc-exp" autocomplete="cc-exp" placeholder="•• / ••" required class="col-md-2">
</div>
<div class="form-group">
<label for="cc-cvc" class="control-label">CVC:</label>
<input id="cc-cvc" data-stripe="cvc" type="tel" class="input-lg form-control cc-cvc" autocomplete="off" placeholder="•••" required class="col-md-2">
</div>
<button type="submit" class="btn btn-lg btn-primary">Submit</button>
<h4 class="validation"></h4>
</form>
</div>
</body>
</html>
This form for expiry uses just one field and it will be submitted as mm/yy to validator, validator works fine but after successfull validation, I want to split mm/yy separated and assign each of them to data-stripe="exp-month" and data-stripe="exp-year" respectively before submitting to stripe.js as those two data-stripe="exp-month" and data-stripe="exp-year" are required by stripe.js.
for validator I use this 3rd party script: https://github.com/stripe/jquery.payment/tree/master/lib
I see it has already a feature to split mm and yy here https://github.com/stripe/jquery.payment#paymentcardexpiryvalstring-and-fnpaymentcardexpiryval , but I have no idea how to use that function to split fom expiry date and assign them to data-stripe="exp-month" and data-stripe="exp-year"
Please advice how can I do this?
Stripe.js can accept expiry dates as a single argument: https://stripe.com/docs/stripe.js#passing-exp-dates
So you don't need to split the date. Just adding data-stripe="exp" to the cc-exp field should do the trick:
<input id="cc-exp" data-stripe="exp" type="tel" class="input-lg form-control cc-exp" autocomplete="cc-exp" placeholder="•• / ••" required class="col-md-2">