I'm trying to do is replace the contents of $('#product_blocks') with new html while preserving the jQuery listeners events on a similar element id.
var thenewhtml= '<div id="clickme">hello this text will be replace on click</div>';
$('#product_blocks').html(thenewhtml);
the jquery event:
$( "#clickme" ).click(function() {
$("#clickme").html("yayImChanged");
});
BUT my problem is once I replace #products_block with new html, $("#clickme" ) does not work.. does not carry forward to new html... This is what I'm looking to solve.
You can use jQuery .on() method signature for defining event handlers e.g.
$(document).on('click', '#userclickedhere', yourClickHandlerFunction);
jQuery .on() doc
Updated Answer:
It will still work.
$(document).on('click', '#clickme', function(e) {
$(this).html("yayImChanged");
});
Here is a CodePen demo
Because the page structure looks the same - it's only the content of the span that's been changed - you can select the new content of the span, and replace the old span's content with it:
const $userclickedhere = $('#userclickedhere');
$userclickedhere.on('click', () => console.log('click'));
const thenewhtml = `<span id="userclickedhere">new data</span>`
const newSpanContent = $(thenewhtml).text();
$userclickedhere.text(newSpanContent);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="product_blocks"> <span id="userclickedhere">click me</span> </div>
This will preserve any listeners on #userclickedhere.
(of course, you also need to use .html on jQuery collections to set their HTML - .innerHTML is a method on native DOM elements, which are not the same thing)
You can use DOMSubtreeModified:
const newHtml = '<div id="clickme">hello this text will be replace on click</div>';
const attachEventClickHandler = () => $('#clickme').one('click', () => {
console.log('Clicked...');
$('#product_blocks').html(newHtml);
$('#clickme').on('click', () => {
console.log('yayImChanged...');
$('#clickme').html('yayImChanged');
});
});
$('#product_blocks').one('DOMSubtreeModified', () => attachEventClickHandler());
attachEventClickHandler();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="product_blocks"> <span id="clickme">click me</span> </div>
When jQuery registers an event, it looks for that selector in DOM. it will only register events for only available DOM elements.
Here, you are adding thenewhtml later the jQuery registered the events.
Hence, you have to register click event on #clickme again once after you replace the HTML. just after the line: $('#product_blocks').html(thenewhtml);
This is the flow of jQuery click event on particular selector.
But, there's also an another way to register events on those html elements which do not exist in DOM when page load.
i.e. $(document).on() method.
here you can do it both the ways.
1. define click event after replacing html in #product_blocks.
2. define click event using $(document).on() anywhere.
$(document).on('click','#clickme',function() {
/* your code here */
});
or
$('#product_blocks').html(thenewhtml);
$('#clickme').click(function() {
$(this).html("yayImChanged");
});
Related
Check this fiddle: https://jsfiddle.net/L6poures/
item.click(function()
{
alert("It works")
})
$("#container").append(item)
var stored = item.clone(true, true)
function add_remove()
{
$("#container").html("")
$("#container").append(stored)
}
Basically, if I clone an element with .clone(true, true), after I replace the container with .html and appended again, and repeat that process again, the click event is gone.
Is there something wrong with jQuery or am I doing something wrong?
When you have event listeners in content you add dynamically, it usually simplifies things to use event delegation instead. This means that you attach the event listener to a parent container that is not deleted - in this case your #container element - and you use a selector in the jQuery .on() call to specify which child elements you are interested in.
Here's an updated fiddle that illustrates the technique for your use case, and here it is as a snippet:
$("#container").on( "click", "#item", function() {
alert("It works")
})
var html = "<div id='item'>Hi</div>"
$("#container").html(html)
function add_remove() {
$("#container").html(html)
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='container'></div>
<br>
<button onclick="add_remove()">
Remove And Add Again
</button>
Note that the code doesn't even use .clone() now; it just inserts the HTML code each time without worrying about event listeners at all. You could use .clone() as in your original code, but event delegation gives you the flexibility to do it either way. In any case you wouldn't need the .clone(true,true) arguments because you don't care about preserving event listeners in the inserted code.
Check the below code (have made minor changes to your code, to make it work). You don't even need to clone():
var item = $("<div id='item'>Hi</div>");
$("#container").on('click', '#item', function() {
alert("It works");
});
$("#container").append(item);
function add_remove() {
$("#container").html("").append(item);
alert('cloned and appended successfully.');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='container'></div>
<br>
<button onclick="add_remove()">
Remove And Add Again
</button>
I have a project where I need to load html from an external file and add it to an existing div element.
It works great, except that the .click() events never fire when clicking on the desired icon in the generated html.
Code that loads the html:
$.each(data, function (index, review) {
let html = $.parseHTML($.trim(review));
$(html).appendTo($items);
});
Root element of the loaded html is a class named "lc-rating-wrap".
The js that doesn't fire on click:
$(".lc-rating-wrap > .vote-wrap > .do-vote-wrap > .icon").click(function () {
//doStuff
});
I guess it has something to do with that the elements isnt there when I load the js file?
Am I using parseHTML() correctly?
Your content is dynamic, but your event is binded only for existing elements. Change it to be $(static).on(event, dynamic, callback):
$(document).on('click', ".lc-rating-wrap > .vote-wrap > .do-vote-wrap > .icon", function () {
//doStuff
});
Please use delegate instead click.
$( "#parent" ).delegate( ".icon", "click", function() {
//dostuff
});
Parent is a element which you using to generate your elements (inside).
So it cannot be generated dynamicaly.
use jquery click event delegation. see https://learn.jquery.com/events/event-delegation/
Bind event to an parent element already found in your page when js is binding click event. Use .on("click", "your selector", function(){})
In framework7, how to add click event on dynamic elements?
If I add my element first on my view, the click event works fine like below:
<div class="test">Click Me</div>
$$('.test').on('click', function () {
myApp.alert("Gotcha!");
});
But if I have dynamic elements, especially elements dynamically added to virtual-list, I cannot make the click event to work. What is the right way to do this?
I even tried inline function, ex: <div class="test" onclick="myFunction();">Click Me</div>, still this won't work.
You can use:
// Live/delegated event handler
$$(document).on('click', 'a', function (e) {
console.log('link clicked');
});
For your case:
$$(document).on('click', '.test', function(e){
console.log('Some code...');
});
Here is docs. Scroll until events section.
Use this for dinamically added elements:
$$(document).on('click', '.test', function () {
myApp.alert("Gotcha!");
});
All answers are good to go with. But if you are using this class 'test' for other elements of the page, you will end up firing some extra click event(when you click on any other element of same class). So if you wanna prevent that, you should add listener to that particular element.
if you're adding an element of class test to an existing element of id testId, then use
$('#testId').on('click', '.test', function(this){
}
In the function where you dynamically add the new elements you have to assign an event handler for them.
Lets say you have a function something like this
function addNewLines(){
//add the new lines here
// you have to run this again
$$('.test').on('click', function () {
myApp.alert("Gotcha!");
});
}
I'm using underscore to create some elements and appending them to a div with jQuery.
At the bottom of the page I'm using jQuery's .on() to respond to clicks on the elements.
$('.pickup').on('click',
function(e) {
alert("hello");
}
);
Via some user interaction (in Google maps), I've got to add more elements to the div and want them to respond to clicks as well. For some reason they do not. I've pared it all down on jsfiddle:
http://jsfiddle.net/thunderrabbit/3GvPX/
When the page loads, note that clicking on the lines in output will alert('hello') via jQuery.
But click the [add] button and the new lines do not respond to clicks.
My HTML
<div id="unit_2225" class="pickup">
<span>Click me; I was here first</span>
</div>
<script type="text/template" id="unit-template">
<div class="unit-item">
<span class="pickup">
<span>click us (<%= unit_id %>) via underscore</span>
</span>
</div>
</script>
<div id="divID">
</div>
<button>add</button>
My Javascript
var addUnitToDiv = function(key,val) {
console.log(val);
var template = _.template($('#unit-template').html(),val);
$('#divID').append(template);
}
var unit_ids = [{unit_id:'hello'},
{unit_id:'click'},
{unit_id:'us'},
{unit_id:'too'},
{unit_id:112}];
$.each(unit_ids, addUnitToDiv);
var unit_pids = [{unit_id:'we'},
{unit_id:'wont'},
{unit_id:'respond'},
{unit_id:'to'},
{unit_id:'clicks'},
{unit_id:358}];
createMore = function() {
$.each(unit_pids, addUnitToDiv);
}
$('.pickup').on('click','span',function() {
alert("hello");
});
$('button').click(createMore);
I found a similarly worded question but couldn't figure out how to apply its answer here.
Instead of binding events directly to the elements, bind one event to their container element, and delegate it:
$("#divID").on("click", ".pickup", function () {
// Your event handler code
});
DEMO: http://jsfiddle.net/3GvPX/3/
In this case, the event handler is only executed for elements inside of the container #divID that have the class "pickup".
And in your scenario, the elements are being added to the element with an id of "divID". Thus, where the two selectors came from.
This is handy because, as you've found out, dynamically adding elements doesn't magically bind event handlers; event handlers bound normally with .on() are only executed (bound) on those present at the time of binding.
It could even help if you change the delegated selector to "span.pickup" (if you know the elements will always be a <span> like in your template), so that the DOM is filtered by the tag name first.
Reference:
http://api.jquery.com/on/#direct-and-delegated-events
Working demo http://jsfiddle.net/u2KjJ/
http://api.jquery.com/on/
The .on() method attaches event handlers to the currently selected set of elements in the jQuery object. You can attach the handler on the document level.
Hope it fits the need, :)
code try the code changed below
$(document).on('click','.pickup',function() {
alert("hello");
});
I was under the impression that jquery's on() reacted to events attached elements dynamically added to the dom (via ajax or cloning, etc). However, the following is only working for the element attached to the dom at page load. The other copy I make of it using clone() is not being, well, handled.
$(document).ready(function () {
$('.ship_via_dropdown').on('change', function () {
console.log($(this));
if ($(this).hasClass('prev_change')) {
console.log('has');
} else {
$(this).addClass('prev_change');
console.log('hasn\'t');
}
});
});
Code for cloning:
$(document).ready(function(){
var form1 = $('.line_item_wrapper').children().clone();
$('#new_line_content_1').html(form1);
});
HTML for dropdown (contents added by jquery db query on document ready)
<span class="select ship_via_select_container">
<select class="ship_via_dropdown ship_via_dropdown_1">
</select>
</span>
Thank you for any insight!
Either delegate the event instead:
$(document).on('change', '.ship_via_dropdown', function () {
console.log($(this));
if ($(this).hasClass('prev_change')) {
console.log('has');
} else {
$(this).addClass('prev_change');
console.log('hasn\'t');
}
});
Or better yet, use .clone(true) to clone with events. (Note: this will only work if you're cloning AFTER the event handler is attached.)
It does, but not in the way that you think. When used as you have used it:
$('.ship_via_dropdown').on('change',
It is really not different than using .change(). What you are looking for is event delegation. This takes the following form:
$("<selector to static ancestor>").on('change', '.ship_via_dropdown', function () {
Where <selector to static ancestor> is a selector to a static ancestor of the dynamically added elements. (one that is not dynamically created) As a last resort document can be used here. However for performance, this should be the closest static ancestor element.
jquery's on() reacted to events attached elements dynamically added
No - or at least, only if you use it with delegated events. The live method did always delegate events to the document.
Change this line:
$('.ship_via_dropdown').on('change', function () {
to this:
$(document).on('change',".ship_via_dropdown", function () {