I'm looking for a cross browser compatible way to stop a form submission without returning false.
For example:
<form action="..." onsubmit="someFunc(this);">
...
</form>
<script type="text/javascript">
function someFunc(form){
// do stuff to stop form submission without return false
}
</script>
I've not found a good way to do this, anybody know if its possible?
Edit:
I've tried both form.preventDefault() and window.event.preventDefault() in someFunc(). It seems like neither prevent the form from submitting in firefox (on a mac).
Solution
It seems like window.event is not available in FF, while it is in Chrome and IE.. thus my previous attempts not working. I solved this by having the first parameter of the function being called in the form's onsubmit to be the event itself. That can then be cancelled.
New form onsubmit looks like so: onsubmit="someFunc(event, this);"
You can use the event.preventDefault() function to stop of form from submitting. Here's an of a form being caught before being submitted in Javascript (with some JQuery):
$("form").submit(function(event) { // You can change "form" to whatever ID/class your form has
event.preventDefault();
}
Done it! I've tested it in Firefox and this definitely works
Here's a link to the JSFiddle: http://jsfiddle.net/bZx3e/. Here's the HTML:
<form id="form"><input type="checkbox" id="checkbox"/><label for="checkbox">Checkbox</label>
<input type="button" onclick="check();" value="Submit"/></form>
And here's the Javascript:
function check(){
if(document.getElementById("checkbox").checked){
document.getElementById("form").submit();}
else{}
}
So, basically, if the checkbox isn't checked, do nothing and if it is, submit the form. This way you could have all your validation before submitting the form.
Each event has an Event object associated with it. In the W3C event model, calling event.preventDefaut will prevent the default action from occuring. However, the only way in the W3C model to get a reference to the related event object is to pass it to the function from the associated listener. For an in–line listener:
<form onsubmit="someFunc(event)" ...>
If you attach the listener using addEventListener, then the related event object will be passed to the listener function as the first argument:
someElement.addEventListener('click', foo, false);
function foo(eventObject) {
var target = eventObject.target; // element on which the click occured
var currentTarget = eventObject.currentTarget; // Element that called the listener
}
However, the listener in the OP is attached in–line and does not pass a reference to the event, so it can't be captured in browsers that only support the W3C model.
It the IE event model, the related event object is available as a property of the window object, so within the function you can do:
var event = window.event;
But the IE model doesn't support preventDefault, however does provide a returnValue property that, if set to false, cancels the default action.
So the most cross–browser way without using return false would be:
<form onsubmit="someFunc(event);" ...>
function someFunc(event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
}
However, it is very much simpler to use return false as it has been reliably supported by every browser since about NN/IE 2.
Related
I have action what first need to render form by ajax and then need to update existing values. I already get rendered form with proper values, but when I click to submit form by ajax I cant prevent form submission, I have this script:
$('#edit-comment').click(function (e) {
e.preventDefault();
console.log(1);
});
But submitting with still work ! What I am doing wrong. And I dont know how I need to handle submitted form in the edit action. Here is existing part of it:
/**
* #Route("/edit/comment", name="chat_edit", options={"expose"=true})
*/
public function editAction(Request $request)
{
$comment_id = json_decode($request->getContent(), true)['commentId'];
$comment = $this->get('comment.repository')->find($comment_id);
$form = $this->createForm(new CommentType(), $comment);
return $this->render("ChatCommentBundle:Comment:form.html.twig",
array('form' => $form->createView())
);
}
Link to gist with form type
Update:
The original answer (below) still applies, but given that the form is actually loaded using AJAX, you can't bind the event listeners in the $(document).ready callback. The best option for you is to use event delegation. This is done by attaching an event listener to a DOM element that does exist from the start, but have that listener pick up on events for elements that might be added later on. For example: the body element will always exist, so you can listen for a form submission there, whether or not that form exists doesn't matter:
$('body').on('submit', '#form-id', function(e)
{
console.log('#form-id was submitted, do AJAX => submission stopped');
return false;
//or
e.preventDefault();
e.stopPropagation();
});
The why and how this works is very well explained here. It boils down to the fact that all events pass through all of the parent DOM elements of the target node, so you can attach listeners anywhere in the DOM, and handle the events before they reach their target.
I think this old answer of mine might explain a thing or 2, too. It doesn't use jQ, but it contains a simplified version of the code that jQ uses internally for delegation.
You're preventing the default effects of the click event on $('#edit-comment'), but that event still propagates through to the form. You might want to add e.stopPropagation(), too. Or simply return false; from the callback (which prevents the default and stops propagation).
However, a better way to prevent the form from being submitted is to use the submit event, and stop the submission there:
$('#form-id').on('submit', function(e)
{
console.log('Do ajax call here');
return false;
//or
e.preventDefault();
e.stopPropagation();
});
I could not make preventdefault to prevent action. I apologize if the answer is too easy but I simply cant find the error. why is it not preventing from entering the link? jsfiddle given below.
http://jsfiddle.net/zwY5p/34/
$('#theForm').click(function(e) {
event.preventDefault();
alert('FORM!');
});
e != event
$('#theForm').click(function(event) {
event.preventDefault();
alert('FORM!');
});
The parameter passed to the handler function is what you need to execute preventDefault on. In your code, you are passing e but calling preventDefault on event.
preventDefault prevents the default browser action. It does not cancel the inline JavaScript, since that runs first. If you have to override that, just remove it (no event listener necessary):
$('#theForm').removeAttr('onclick').
your event parameter name e and the variable you are using event are different,
$('#theForm').click(function(event) {
event.preventDefault();
alert('FORM!');
});
Other than the errors pointed out on other answers there's another small issue, specifically in your markup declaration:
<!-- Use either the closing tag or the slash (/) in the opening tag -->
<button id="theForm" onclick="location.href='http://www.example.com'" />
go to google
</button>
On the topic, you have two different handlers attached to the button element, they are both handling the click event but they are still different and separate things. jQuery won't know about the handler defined in the markup:
var btn = document.getElementById('theForm');
jQuery._data( btn, "events" );
will return an array with a single element which is the handler added via jQuery.
Now you have to re-evaluate the need of two different handlers for the same element and event and apply conditions. Do you really need to do it this way?
You're using 2 'click' events.
You end up using preventDefault once, and it's used after the 1st click event has ran.
If you make your button an href, then your preventDefault will be working.
It will also make more sense, as the JS will be separated from the HTML markup.
Also, of course you must use the same parameter name. (function(event), with event.preventDefault for example).
If you are passing "e" as an event to the function then you should prevent the default action only for that "e" that you have passed and not for "event".
$('#theForm').click(function(e) {
e.preventDefault();
alert('FORM!');
});
jQuery preventDefault() method: http://api.jquery.com/event.preventDefault/
The HTMLFormElement DOM interface provides the .submit() and .reset() methods, which I'm heavily making use of in my single-page app.
Right now I'm trying to figure out the relation between these two methods and triggering the form element's onsubmit and onreset event handler methods.
Test case
So considering this perfectly valid HTML5 document:
<!DOCTYPE html>
<title>HTMLFormElement method-event relation test page</title>
<form style="border:solid">
<input name=foo>
<button>Submit</button>
<button type=reset>Reset</button>
</form>
<button id=js-submit>.submit()</button>
<button id=js-reset>.reset()</button>
And the following JS <script> content right below the form:
(function() {
var qs = function(s) {
return document.querySelector(s);
},
form = qs('form');
form.onsubmit = function(e) {
console.log('onsubmit fired');
return false;
};
form.onreset = function(e) {
console.log('onreset fired');
return false;
};
qs('#js-submit').onclick = function() {
form.submit();
};
qs('#js-reset').onclick = function() {
form.reset();
};
}());
Live demo
* Side-note: I know addEventListener may be preferred over onevent handlers, however it'd have the same effect and this is merely a simple, IE8-compatible illustration.
Clicking the Submit and Reset buttons inside the form fire the corresponding onsubmit and onreset methods just fine, as these are user actions the event handlers must be triggered.
The buttons outside of the form call the form element's .submit() and .reset() methods, that is, the methods which I'm programmatically calling in my real code.
Normally, as I'm programmatically calling simple form methods from code-side, I'd expect these to not trigger any form event.
However, clicking the .reset() button does dispatch an onreset event to the form, while .submit() does not dispatch any event to the form. Tested in Chrome, Firefox and IE8.
* The behavior is the same when using addEventListener instead of on* handlers.
Question
Is there a standard expected behavior for whether event handlers will be triggered when a form's .submit() and .reset() methods are called?
The .submit() method is not warranted to (and most often does not) trigger the onsubmit event due to historical reasons. It is worth noting that modern browsers (latest Chrome, Firefox, Opera, Safari and even IE8) do not trigger the onsubmit event when calling form.submit().
The .reset() method in the other hand, follows the spec and performs the same action as clicking a reset button, which includes dispatching the onreset event to the form. Tested in the same browsers as the paragraph above.
Reference
HTMLFormElement.submit MDN page:
The form's onsubmit event handler (for example, onsubmit="return
false;") will not be triggered when invoking this method from
Gecko-based applications. In general, it is not guaranteed to be
invoked by HTML user agents.
DOM Level 2 Recommendation:
Methods
reset
Restores a form element's default values. It performs the same action as a reset button.
submit
Submits the form. It performs the same action as a submit button.
[...]
Note: The onsubmit even handler is not guaranteed to be triggered when invoking this method. The behavior is inconsistent for historical reasons and authors should not rely on a particular one.
W3C mailing list:
submit
Submits the form. It performs the same action as a submit button.
I don't think the last sentence is correct. Using a submit input will
trigger onsubmit. The submit method will not. [...]
The accepted answer remains valid in 2022.
I just wanted to add a note, that there are still inconsistencies between browsers today.
For example if you dispatch a custom event named reset on a form element, chrome will ignore it, but firefox will actually reset the form as if you called form.reset() or clicked a reset button.
I have a button in ASP.NET, that renders to HTML as such:
<input id="btn" type="submit" value="clickme">
If I then add the jquery:
$('#btn').click(function(){return false;});
Every time the button is clicked, nothing will happen (i.e. no postback).
This is fine.
Is there any way in Javascript I can programatically invoke the click (which will cause a postback) whilst also disregarding the jquery-attached, return false function?
You can have the event handler accept additional arguments. When triggering the handler with .trigger you can specify values for these arguments, which will let the handler modify its behavior accordingly.
For example:
$("#btn").click(function(event, submitForm) {
submitForm = submitForm || false;
if (!submitForm) return false;
});
// This will not submit the form
$("#btn").trigger("click");
// But this will
$("#btn").trigger("click", true);
The button itself does nothing by default except submitting the form, so try this:
$('#btn').closest('form').submit();
I'm writing some unit tests for an HTML 5 app that uses the HTML 5 form validation API. I've attached a submit event handler to the form that does some custom handling before serializing to JSON and passing it off to my server.
What I've discovered, though, is that if I initiate a jQuery submit() event on the form, even if it's invalid, my submit handler still gets called.
Instead, I'd expect my event handler not to have been called because the form is invalid.
I've created a JSFiddle to demonstrate (tested in Chrome 20):
http://jsfiddle.net/jonbca/SYg4h/22/
So, what gives?
Triggering the ".submit()" handler simply does not have anything to do with the HTML5 form validation mechanism. That mechanism is really quite independent of JavaScript, and in fact it's mostly unavailable from the DOM API. You can explicitly call "checkValidity()" on a form element, but that just returns a boolean result and does not do any of the visual form updates that happen when the user clicks a "submit" form control.
It's important to keep in mind that many of the fancy HTML5 "smart markup" behaviors are designed to allow things to happen without the need for JavaScript.
Try triggering the submit button:
$('#submitBtn').click();
If you don't have one, just do a hidden one, that replicates the action.
Fiddle: http://jsfiddle.net/SYg4h/30/
Try using a click handler on the button
$('#myform').submit(function (e) {
// check for validation here
var value = $('#foo').val();
if (!value || value == undefined)
$('#message').html('It did not submit');
else
$('#message').html("It submitted");
return false;
});
$('#submitBtn').click(function(){
$('#myform').submit();
});
Try this: http://jsfiddle.net/Cqzcu/4/