Code:
var formElement = document.querySelector('form');
formElement.addEventListener('submit', function (e) {
e.preventDefault();
console.log('addEventListener event handler');
this.submit(); // not causing recursive call.
}, false)
</script>
Why isn't going as recursive event handling. I thought this.submit() will call the function/event handler (under which it exists) again. I don't face any issue with this , but just want to know how it is working and not as a recursive call.
Calling .submit on the form itself doesn't trigger an event, it just submits the form. therefore, the event handler doesn't get executed because there is no event.
Related
If I have the following event handler bound to my form:
form.addEventListener('submit', function(evt) {
evt.preventDefault();
console.log('submitted');
this.submit();
});
When the form is submitted by the client, the event handler is executed and the form is submitted without the event handler being executed again.
However, the same logic doesn't apply when attaching click handlers to anchor elements:
a.addEventListener('click', function(evt) {
evt.preventDefault();
console.log('clicked');
this.click();
});
The event handler is executed twice and the link is never followed.
I have two questions:
Why does it appear to work differently for submit vs click?
Why does the anchor's click handler only get executed twice and not indefinitely, if the event handler is being executed each time it's called?
Form submission and element click are different actions, they don't have to behave in the same way.
When using the submit method of the form, the standard says:
Submits the form, bypassing interactive constraint validation and without firing a submit event.
This can be seen also in the submission algorithm. Item 6 checks, whether the action comes from the submit method of the form, and skips the validation and event firing if the "submit()" flag is set.
element.click sets "click in progress flag", which is checked internally before creating a syntehtic click event which calls the hander function. This prevents a click on an element to lead to infinite recursive click event handler calls.
I have this code:
and I would like to add at runtime by JS something like this:
My idea was doing like this but I dont know how to add AND operator:
form.addEventListener('submitForm', function (e) {
e.preventDefault();
alert('onclick handler called');
}, false);
To not change the HTML itself you can do this
window.addEventListener("load",function() {
let saveBut = document.querySelector('a[title="Save"]');
let form = document.querySelector("[name=thisForm]");
form.addEventListener("submit",function(e) { e.preventDefault(); }); // stop submission by other means than the link
saveBut.onclick=null; // remove the inline event handler
saveBut.addEventListener("click",function(e) {
e.preventDefault(); // stop the link's click
if (validate(e, form)) submitForm(form); // call submitForm if valid
});
});
'submitForm' is referenced as a function in your onclick attribute, but you're trying to use it as an event. It won't work like that, <form> doesn't emit an event called 'submitForm', and it's not being called when you call a submitForm function. <form> does have a submit event.
You should avoid using the onclick attribute (and other on* attributes). Use IDs and addEventHandler to add a click event handler. Then you can just write an entire multi-line function in that handler.
You can also use an <input> or <button> of type=submit and then add an event listener of type submit to the form (if your form is a <form> element). Then you will not need to call any other functions from event listeners. The form will handle that.
I'm learning how to use jQuery and I'd like to understand what the purpose of using the off() method before submitting a form is. For example, in the following code, the form is first prevented from sending using preventDefault(), some Ajax is done and when finished, the form is finally submitted. But why do I need to use off() before submit()?
$(document).ready(function() {
$('form[name="Payment"]').on('submit', function( e ) {
e.preventDefault();
AjaxCall();
$(document).ajaxStop(function() {
$('form[name="Payment"]').off('submit').submit(); // Once Ajax request are finished, submit the form.
});
});
});
Because triggering the same event would run all that same event handler code again.
The default would always be prevented, the ajax would be called ....and then the event would be triggered again and you would have an infinite loop without changing something.
Removing the event listener would make any subsequent submit use browser default process
There are other ways around this...but this answer explains what was asked
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've got a web app which I'm trying to make run as fast as possible, one of the ways is by reducing the amount of event listeners I have attached.
I have a lot of forms (around 12). I currently check if they are submitted with:
$('#form-id').on('submit', function(){
//actions here
});
for each form. Is there a way I can do this but with only attaching one listener for a submit? and then doing a switch statement based on the forms ID to decide what actions to do?
Use delegation for submit event for all selected forms. $(this) will be the current form.
$(document).on("submit", "form", function () {
// actions here
// $(this).something...
return false;
});
return false is used to prevent the default browser behavior.
Use event delegation
$(document).on('submit', 'form', function(e) {
e.preventDefault();
// ....
});
This adds just one listener to the document which gets called anytime a form is submitted.
You can use
$('form').on('submit', function() {
//you can use $(this).attr('id') to get id of submitted form
}
to catch submit event for all form.