How to attach all events after manipulating the dom using ajax response. I have a ajax request which get a html response which is basically a fragment of html. that fragment HTML have many buttons. I want to refresh the dom so previously declared and attached events be applied into that fragment too. I dont want to keep on adding each events for each button using jquery on(). how else to do it?
You can use delegated event handling which is set up ahead of time and can be made to apply to newly added DOM elements. Delegated event handling is done with .on() and generally takes the form of:
$("static parent selector").on('click', 'selector for dynamic element', fn);
There is no clean way to just run your event installing code again and have it only apply to newly added DOM elements. You would have to put that code in a function and code it such that it never adds an event handler more than once and then you could call that function again after adding items to the DOM. Or, you could make the function take an argument for a parent object and only add event handlers in the newly added DOM hierarchy.
Here's another relevant answer about delegated event handling: Does jQuery.on() work for elements that are added after the event handler is created?
Related
This question already has answers here:
Event binding on dynamically created elements?
(23 answers)
Closed 7 years ago.
I have a <select> form element that is being generated dynamically after the page loads. I was using jQuery to attach a change event that would update other fields in the form, and wanted to eliminate the need to rewire the handler each time the form containing the <select> was replaced.
For click events on dynamic elements, I have been moving to unobtrusive JavaScript and wanted to use that approach for change - but no success. Attaching to the <select>directly was cumbersome because when the node is replaced in the DOM, the connected event listener dies with it, and the new node must be attached to again.
So I wanted to know, is there a way to unobtrusively assign a change event handler to the parent element of a newly-created <select> and let the event bubble up to a handler on a previously-existing element, in order to avoid attaching a handler each time a new target input element is created?
Yes!
$('#StaticParentNode').on('change',"select.qualifiers", function(){
alert("Change detected from parent");
});
Naturally, I finally got this working 2 minutes after posting my original answer (below). Doh.
No.
While attaching unobtrusive event listeners on a parent <div> or the document works great for bubbling click events from elements that didn't previously exist on the page, you can only attach an event listener to an element that has that type of event.
As stated in the jQuery .change API docs (although this issue is not jQuery specific):
The change event is sent to an element when its value changes. This event is limited to <input> elements, <textarea> boxes and <select> elements.`
Since <div> and document do not have a change event, they cannot intercept one from their children either.
Solutions:
Just set onchange to a previously-defined function when you generate the element: <select onchange='MyModule.selectChanged()'>[<options>]</select>. Not pure from a separation of concerns standpoint, but a simple approach with minimal extra HTML added to an AJAX request, and no fiddling with handlers after the AJAX call completes.
or,
(Re)attach an event listener each time you create new elements that require it, either 'manually' (e.g. in a $.ajax success function) or by wiring it into whatever tool is handling your AJAX results (e.g. modifying or extending .prototype). See examples elsewhere on SO.
How to attach all events after manipulating the dom using ajax response. I have a ajax request which get a html response which is basically a fragment of html. that fragment HTML have many buttons. I want to refresh the dom so previously declared and attached events be applied into that fragment too. I dont want to keep on adding each events for each button using jquery on(). how else to do it?
You can use delegated event handling which is set up ahead of time and can be made to apply to newly added DOM elements. Delegated event handling is done with .on() and generally takes the form of:
$("static parent selector").on('click', 'selector for dynamic element', fn);
There is no clean way to just run your event installing code again and have it only apply to newly added DOM elements. You would have to put that code in a function and code it such that it never adds an event handler more than once and then you could call that function again after adding items to the DOM. Or, you could make the function take an argument for a parent object and only add event handlers in the newly added DOM hierarchy.
Here's another relevant answer about delegated event handling: Does jQuery.on() work for elements that are added after the event handler is created?
Hi I'm developing my view in JS and I'm stuck in binding a click handler for my horizontal layout element. I've tried using Jquery
$("#myHorizontalLayout").bind("click",function(){window.alert()});
Which didn't work then I tried using attachPress with the element which obviously didn't exist. Please help.
Update:
The JS view is the default view of the application.
When on/bind does not work, it could be that the HTML of the control has actually not been created yet at this point in time. But even if you delay the binding, the re-rendering (re-creation of the HTML after changes) would remove your listener, at least when bound on the control itself.
A proper way of doing this is using the generic attachBrowserEvent function available on every control (here: on the layout) which internally handles all the rendering/rerendering stuff, see this example:
http://jsbin.com/hijutunefi/1/edit?html,output
attachBrowserEvent works for any browser event, as it attaches a new browser event listener to the root node of the control. For the most common browser events UI5 does event delegation, so for the "click" event and several others addEventDelegate can also be used, as pointed out by aborjinik.
Alternatively, listening on the <body> level with normal jQuery mechanisms should in general also work.
Which didn't work then I tried using attachPress with the element which obviously didn't exist. Please help.
Does this means that the element on which you are attaching event handler doesn't exists at this point? If this is the case you can hook the handler to some container, upper in the DOM hierarchy which you are sure that exists and filter the click events.
Example:
$("body").on("click", "#myHorizontalLayout", function(){
alert("Hey, you!");
});
As of jQuery 1.7, the .on() method is the preferred method for
attaching event handlers to a document. For earlier versions, the
.bind() method is used for attaching an event handler directly to
elements. Handlers are attached to the currently selected elements in
the jQuery object, so those elements must exist at the point the call
to .bind() occurs.
Reference here
So try replacing bind with on and let me know if it works or not.
This question already has answers here:
Direct vs. Delegated - jQuery .on()
(6 answers)
Closed 9 years ago.
What is the difference Between the following statements. Which one should I choose over one another in a situation.
$(document).on("click","#btn",callback);
$("#btn").on("click",callback);
Have a look at the event delegation jQuery documentation
basically
$(document).on("click","#btn",callback);
will bind the click to the document DOM rather than the element directly which is useful when you are appending DOM elements to the window in which case the #btn selector will not exist yet.
Basically wiht direct
$(document).on("click","#btn",callback);
you're assigning events to document that affect matching descendants (#btn) which may or may not exist at the time that line of code is run.
$("#btn").on("click",callback);
With delegated you're affecting all matching elements that do exist at the time that line of code is run, and no matching ones that are created later.
http://api.jquery.com/on/
Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the call to .on(). To ensure the elements are present and can be selected, perform event binding inside a document ready handler for elements that are in the HTML markup on the page. If new HTML is being injected into the page, select the elements and attach event handlers after the new HTML is placed into the page. Or, use delegated events to attach an event handler, as described next.
Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time. By picking an element that is guaranteed to be present at the time the delegated event handler is attached, you can use delegated events to avoid the need to frequently attach and remove event handlers. This element could be the container element of a view in a Model-View-Controller design, for example, or document if the event handler wants to monitor all bubbling events in the document. The document element is available in the head of the document before loading any other HTML, so it is safe to attach events there without waiting for the document to be ready.
direct
$("#btn").on("click",callback);
Element with id present in DOM get clicked call callback. If it is
present in DOM handler will get attached.
binds the event listener directly to the elements
delegated
Read Event Delegation.
Use .on()
$(document).on("click","#btn",callback);
When a element in document is added with id btn than on click of that element run
callback function .
Binds the event listener to the document object
Syntax
$( elements ).on( events, selector, data, handler );
I have lot of jquery scripts which dont handle elements loaded or created on the fly, of course I can convert all my scrits and add the them the .live() function. However was wondering if there is any option or trick that could automatically simulate the live function in all the scripts without modifying them one by one manually.
Thanks for the comments , live is depreciated, so I restate my question with the .on() function.
There is not one trick that will make all existing event handler code work with dynamically loaded elements without updating each event handler unless you want to replace some jQuery methods with methods that work differently than jQuery has documented (not recommended). You would have to replace all jQuery event handling methods that you are currently using with methods that forced delegated event handling into them. This would be a bad way to do this. Not only would you be hacking jQuery into something that would be different than it is documented and opening yourself up to compatibility issues with other code, but you'd be forced into the most inefficient use of delegated event handling (which is why .live() was removed in the first place). Do not do this. Fix your code to use the proper method of delegated event handling. It's not hard at all.
.live() has been deprecated and even removed from the latest versions of jQuery. You should not use it. There is a form of .on() that will allow you to use delegated event handling for dynamically loaded objects. You can see how to use the proper form of .on() for dynamically loaded elements in this post: jQuery .live() vs .on() method for adding a click event after loading dynamic html.
The "proper" way to use .on() for dynamic elements is like this:
$('#parent').on("click", "#child", function() {});
where you select the closest parent to the dynamic element that is not itself dynamically loaded and bind the event handler to that element.
.live() was removed because it put all delegated event handlers on the document object somewhat analogous to this:
$(document).on("click", "#child", function() {});
If, however, you used a number of delegated event handlers like this, performance could start to bog down. That's because when you do it this way and you click anywhere in the document and that click bubbles up to the document, it has to compare every single selector in every single .live() event handler you had to the current clicked object. Since selector comparisons are not always fast, this could really bog down the processing of events.
When you place the event handler on an object closer to the actual object, you end up with far event handlers there and thus far fewer selectors to compare to and processing of the events works faster.
Here's a reference on some differences between static event handlers and delegated event handlers and some useful notes on them: JQuery Event Handlers - What's the "Best" method