I have a checkout form on my website that uses a custom validation method implemented with Bootstrap. It has a JavaScript function to prevent the form from being submitted multiple times if it is filled out correctly. I'm using a technique commonly suggested on SO to disable the submission, albeit with vanilla JavaScript instead of JQuery. This is the function:
function submitForm() {
// 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(thisForm) {
event.preventDefault();
if (thisForm.checkValidity() === false) {
event.stopPropagation();
}
thisForm.classList.add('was-validated');
<?php if(isset($shipping)){
echo "stripe.createToken(card).then(function(result) {
if (result.error) {
// Inform the user if there was an error
} else {
thisForm.addEventListener('submit', function(event){
event.preventDefault();
return false;
});
// Send the token to the server
console.log('Sending token ' + result.token + '.');
}
});";
}?>
});
};
The form is created like this:
<form id="payment-form" onsubmit="return submitForm()" class="needs-validation" novalidate>
When I test the page with the form filled out correctly, double clicking the submit button prints the "Sending token" message to the console twice when it should only happen once. I thought maybe it was because it was taking too long to get to the part of the function where the form is disabled, but the message prints again no matter how many times the button is clicked.
Using inline event handlers is bad practice and results in poorly factored, hard-to-manage code. Seriously consider attaching your events with JavaScript, instead, eg: https://developer.mozilla.org/en/DOM/element.addEventListener
You're not calling the validation function with the event of when the form was clicked - and then you reference event.preventDefault();, but event is not defined.
Try something like this instead. Remove the onsubmit attribute, and do:
[...document.querySelectorAll('.needs-validation')].forEach((thisForm) => {
thisForm.addEventListener('submit', (event) => { // add the event argument here
event.preventDefault();
if (thisForm.checkValidity() === false) {
// rest of your code
(though, I don't see why you're using .filter in the first place it doesn't make sense here - did you mean to use forEach? And if there's only one #payment-form, couldn't you have selected that by itself?)
To stop a form from submitting you should call event.preventDefault() or return false;
<form onsubmit="handleSubmit"></form>
handlesubmit(event) {
event.preventDefault();
// or return false;
}
Related
I wanna write my own form validation javascript library and I've been looking on google how to detect if a submit button is clicked but all I found is code where you have to use onClick on onSubmit="function()" in html.
I would like to make this javascript so that I don't have to touch any html code like adding onSubmit or onClick javascript.
Why do people always use jQuery when it isn't necessary?
Why can't people just use simple JavaScript?
var ele = /*Your Form Element*/;
if(ele.addEventListener){
ele.addEventListener("submit", callback, false); //Modern browsers
}else if(ele.attachEvent){
ele.attachEvent('onsubmit', callback); //Old IE
}
callback is a function that you want to call when the form is being submitted.
About EventTarget.addEventListener, check out this documentation on MDN.
To cancel the native submit event (prevent the form from being submitted), use .preventDefault() in your callback function,
document.querySelector("#myForm").addEventListener("submit", function(e){
if(!isValid){
e.preventDefault(); //stop form from submitting
}
});
Listening to the submit event with libraries
If for some reason that you've decided a library is necessary (you're already using one or you don't want to deal with cross-browser issues), here's a list of ways to listen to the submit event in common libraries:
jQuery
$(ele).submit(callback);
Where ele is the form element reference, and callback being the callback function reference. Reference
<iframe width="100%" height="100%" src="http://jsfiddle.net/DerekL/wnbo1hq0/show" frameborder="0"></iframe>
AngularJS (1.x)
<form ng-submit="callback()">
$scope.callback = function(){ /*...*/ };
Very straightforward, where $scope is the scope provided by the framework inside your controller. Reference
React
<form onSubmit={this.handleSubmit}>
class YourComponent extends Component {
// stuff
handleSubmit(event) {
// do whatever you need here
// if you need to stop the submit event and
// perform/dispatch your own actions
event.preventDefault();
}
// more stuff
}
Simply pass in a handler to the onSubmit prop. Reference
Other frameworks/libraries
Refer to the documentation of your framework.
Validation
You can always do your validation in JavaScript, but with HTML5 we also have native validation.
<!-- Must be a 5 digit number -->
<input type="number" required pattern="\d{5}">
You don't even need any JavaScript! Whenever native validation is not supported, you can fallback to a JavaScript validator.
Demo: http://jsfiddle.net/DerekL/L23wmo1L/
This is the simplest way you can have your own javascript function be called when an onSubmit occurs.
HTML
<form>
<input type="text" name="name">
<input type="submit" name="submit">
</form>
JavaScript
window.onload = function() {
var form = document.querySelector("form");
form.onsubmit = submitted.bind(form);
}
function submitted(event) {
event.preventDefault();
}
Based on your requirements you can also do the following without libraries like jQuery:
Add this to your head:
window.onload = function () {
document.getElementById("frmSubmit").onsubmit = function onSubmit(form) {
var isValid = true;
//validate your elems here
isValid = false;
if (!isValid) {
alert("Please check your fields!");
return false;
}
else {
//you are good to go
return true;
}
}
}
And your form may still look something like:
<form id="frmSubmit" action="/Submit">
<input type="submit" value="Submit" />
</form>
If you have multiple forms in same page & you wants to handle submit event Listener without using Id
jQuery
$('form').submit(function (event) {
targetObj = event.target;
// do your logic
});
Pure JavaScript trick
Onload just do below way.
for(var i=0; i<document.forms.length; i++){
var form = document.forms[i];
form.addEventListener("submit", myListener,false);
}
credit :- Multiple Form Submit Event Listener Handling using JavaScript credit goes to Jan Pfeifer's Answer on StackOverflow Community
I hope this helps to someone
With jQuery:
$('form').submit(function () {
// Validate here
if (pass)
return true;
else
return false;
});
I wanna write my own form validation javascript library and I've been looking on google how to detect if a submit button is clicked but all I found is code where you have to use onClick on onSubmit="function()" in html.
I would like to make this javascript so that I don't have to touch any html code like adding onSubmit or onClick javascript.
Why do people always use jQuery when it isn't necessary?
Why can't people just use simple JavaScript?
var ele = /*Your Form Element*/;
if(ele.addEventListener){
ele.addEventListener("submit", callback, false); //Modern browsers
}else if(ele.attachEvent){
ele.attachEvent('onsubmit', callback); //Old IE
}
callback is a function that you want to call when the form is being submitted.
About EventTarget.addEventListener, check out this documentation on MDN.
To cancel the native submit event (prevent the form from being submitted), use .preventDefault() in your callback function,
document.querySelector("#myForm").addEventListener("submit", function(e){
if(!isValid){
e.preventDefault(); //stop form from submitting
}
});
Listening to the submit event with libraries
If for some reason that you've decided a library is necessary (you're already using one or you don't want to deal with cross-browser issues), here's a list of ways to listen to the submit event in common libraries:
jQuery
$(ele).submit(callback);
Where ele is the form element reference, and callback being the callback function reference. Reference
<iframe width="100%" height="100%" src="http://jsfiddle.net/DerekL/wnbo1hq0/show" frameborder="0"></iframe>
AngularJS (1.x)
<form ng-submit="callback()">
$scope.callback = function(){ /*...*/ };
Very straightforward, where $scope is the scope provided by the framework inside your controller. Reference
React
<form onSubmit={this.handleSubmit}>
class YourComponent extends Component {
// stuff
handleSubmit(event) {
// do whatever you need here
// if you need to stop the submit event and
// perform/dispatch your own actions
event.preventDefault();
}
// more stuff
}
Simply pass in a handler to the onSubmit prop. Reference
Other frameworks/libraries
Refer to the documentation of your framework.
Validation
You can always do your validation in JavaScript, but with HTML5 we also have native validation.
<!-- Must be a 5 digit number -->
<input type="number" required pattern="\d{5}">
You don't even need any JavaScript! Whenever native validation is not supported, you can fallback to a JavaScript validator.
Demo: http://jsfiddle.net/DerekL/L23wmo1L/
This is the simplest way you can have your own javascript function be called when an onSubmit occurs.
HTML
<form>
<input type="text" name="name">
<input type="submit" name="submit">
</form>
JavaScript
window.onload = function() {
var form = document.querySelector("form");
form.onsubmit = submitted.bind(form);
}
function submitted(event) {
event.preventDefault();
}
Based on your requirements you can also do the following without libraries like jQuery:
Add this to your head:
window.onload = function () {
document.getElementById("frmSubmit").onsubmit = function onSubmit(form) {
var isValid = true;
//validate your elems here
isValid = false;
if (!isValid) {
alert("Please check your fields!");
return false;
}
else {
//you are good to go
return true;
}
}
}
And your form may still look something like:
<form id="frmSubmit" action="/Submit">
<input type="submit" value="Submit" />
</form>
If you have multiple forms in same page & you wants to handle submit event Listener without using Id
jQuery
$('form').submit(function (event) {
targetObj = event.target;
// do your logic
});
Pure JavaScript trick
Onload just do below way.
for(var i=0; i<document.forms.length; i++){
var form = document.forms[i];
form.addEventListener("submit", myListener,false);
}
credit :- Multiple Form Submit Event Listener Handling using JavaScript credit goes to Jan Pfeifer's Answer on StackOverflow Community
I hope this helps to someone
With jQuery:
$('form').submit(function () {
// Validate here
if (pass)
return true;
else
return false;
});
I have an ASP.Net WebForms application where I am using jQuery validation. There are several buttons to submit the form, each with different options on the back end.
I have a custom validateForm() function that I can assign to the OnClientClick event of all the buttons, but I'm hoping for a more elegant solution where I don't have to specifically give each button the OnClientClick property.
So basically, is it possible to capture the $(form).submit() event before an asp button is submitted? Without using the OnClientClick attribute?
Solved: My issue was actually not because I couldn't catch the submit, but because the buttons were <a> links instead of inputs. I didn't realize this and made the post while at home trying to fix it from memory.
Any of the below solutions should work in the scenario above with actual submit buttons
Just attach a listener to the submit event:
$('form').on('submit', function (event) {
// Do whatever you need to do here ...
// You could also do `event.preventDefault();`,
// if you wanted to stop the submit.
});
You can use onsubmit event that will execute a JavaScript when a form is submitted from any button.
<form id="form1" runat="server" onsubmit="return ValidationFunction();">
And your JS function should return true or false as
function ValidationFunction() {
// Your jQuery validation
if (isValide) {
return true;
}
else {
return false;
}
}
Another option using JQuery to attaches an event handler to form submission
$(document).ready(function () { // << to make sure DOM is loaded
$('#form1').on('submit', function (e) {
e.preventDefault(); // << the default action of the event will not be triggered
var isValide = false;
if (isValide) {
alert('ok');
this.submit();
}
else {
alert('Not Valid');
}
});
});
I have a form in that I have User Id availability check. So if Id is already in DB it will show a message "Id is already in use". In that case I have to avoid submitting the form. For that my html is as follow,
<div>
<label><strong>Teacher Id:</strong></label>
<input type="text" name="teacherId" id="teacherId" placeholder="Enter Teacher Id" >
</div><span class="status" id="status"></span>
Here span will have the text about availability,
The value to span comes form jquery post call,
$.post('<%=request.getContextPath()%>/controller/TeacherIdCheckController',
{'teacherId':teacherId},
function(data)
{
$('.status').html(data);
});
}
This works fine, to prevent submitting I wrote javascript function as,
function checkTeacherId(){
alert(" in checkTecherId()");
var status=$("#status").text();
alert(status);
if(status=="Id in use try another")
preventDefault();
else
return true;
}
Everything works fine but this javascript function is not working fine so I cant able to prevent submit in case of Id already exist in DB. So please anyone help me in this.
Just because you need to pass the event in the function's arg:
function checkTeacherId(e){ // <---pass the event here
.....
if(status=="Id in use try another")
e.preventDefault(); // and stop it here using dot notation
else
return true;
}
As per your comment you can pass the event to your function in your onclick handler:
onclick="checkTeacherId(event);"
Fiddle
Okay! As #Sanjeev tried commenting on best approach for this work then as you are using jQuery then you can just do this as per best approach like Unobrusive Javascript (removing this inliner scripts just like above posted):
function checkTeacherId(e){ // <---pass the event here
.....
if(status=="Id in use try another")
e.preventDefault(); // and stop it here using dot notation
else
return true;
}
$(function(){
$('#yourformid').on('submit', function(e){
checkTeacherId(e);
});
});
Use this approach if you want to externalize your scripts as declare the function in global scope and put your event handler in doc ready with submit event.
Updated fiddle with unobtrusive way.
Solution as per best practice for form validation:
You have implemented form submit via Submit button and not through js like document.getElementById("myForm").submit();
I don't see any point in using onclick handler on submit button for validation, use the native onsubmit Event Attribute, else you will keep on breaking submit flow.
onsubmit is made for validating form and stopping form submission if validation fails.
This will work sure shot in all browsers and is the correct approach for form validation
Example:
<form action="demo_form.asp" onsubmit="return checkTeacherId()">
function checkTeacherId(){
var status=$("#status").text();
if(status==="Id in use try another"){
return false
}
else{
return true;
}
}
<form method="post" action="/Order/CheckOut/" onSubmit="return Validate()">
and then...
function Validate() {
alert($("#email").val());
return false;
}
The messed up part is when I take out the alert it works fine, the submit fails, but when I put the alert in, it allows the submit to go through... what the heck?
I also tried this:
function Validate() {
if(document.getElementByID("email").value == "test"){
alert("It says test.");
}
return false;
}
and got the same behavior, it would never make it to the return statement...
If I step through the JS with firebug and break at the alert or the if (depending on the version above) it stops there, and I click 'step into' and it just submits the form, why isn't it making it to the return false line?
Why not wrap it in a try block?
function Validate() {
try {
alert($("#email").val());
} catch (e) {
alert("Problem: " + e);
}
return false;
}
You could use event.preventDefault() instead.
$("form[name='myForm']").submit(function(e){
e.preventDefault();
alert($("#email").val());
});
You should attempt to keep your javascript, css, and html all seperate. Don't integrate them, or you'll make the project more difficult to manage. Instead of using the onsubmit attribute in HTML, simply append your logic to the $.submit() method of the form from your javascript as I did above.
This example assumes that you've given your form a name of "myForm." I merely used this in the example as you should itendify which form you're handling the submit-event of, and not use a generic $("form") selector.
If you're already using jQuery you're doing the whole thing wrong to begin with. You shouldn't be manually specifying the onSubmit handler from within the <form> element. Do as #Jon suggested and just bind the submit event:
$("form").submit(function() {
alert($("#email").val());
return false;
});
The problem isn't that your function is returning true. The problem is that the JavaScript in the alert is failing and JavaScript quits interpreting the code. At which point, the browser is continuing with the default action which is to submit the form.
This is why Jonathan Sampson suggests using e.preventDefault() before the alert(), this way the browser doesn't continue with its default behaviour when the alert() fails.