Let say I have 5 element from PHP query (so it is dynamic)
Illustrated below:
element 1 class=element id=id_1
element 2 class=element id=id_2
element 3 class=element id=id_3
element 4 class=element id=id_4
element 5 class=element id=id_5
We ussulay use jquery event by knowing their class or id, but in this case, we don't know exactly their id.
$("#id_3").click(function()
{
//in this case we have known we want to add event when we click id_3
});
How to deal with dynamic element from PHP query?
For example, how can we know that we click on element 3 with id_3?
What must we fill in $(????).click();?
When I use class, how can I know which id I reference from the class clicked?
This was the only way I could get it to work. For example, if you wanted to get the attribute ID or the value of the element that has been clicked...
$("containerElem").on("click", "someElemID", function(evt) {
var getElemID = $(evt.target).attr("id");
var getVal = $(evt.target).val();
});
In your example the elements all have the same class, so you can setup your event handler based on that:
$(".element").click(function() {
// "this" refers to the clicked element
// this.id will be the id of the clicked element
});
Or if these elements are dynamic in the sense of being loaded via Ajax at some point after the initial page load use a delegated event handler:
$("somecontainerelement").on("click", ".element", function() {
// do something with this.id
});
Where "somecontainerelement" would ideally be the element that the dynamic elements are added to, but could just be document.
If they all have the same class, then you can use a class selector. Then use this to find whatever property you are after.
$('.element').click(
$(this).prop('id');
);
If you want to add a click only then why not add that to the generated html on server side?
You can use attribute starsWith selector & on to bind events on dynamically created elements.
$('body').on('click', '[id^=id]', function(e){
});
This is veryusefull when we work on unknown elements with id or class
$( document ).ready(function() {
// user this if element is div
$('div[id^="id_"]').on('click', function() {
alert($(this).attr('id'));
});
// user this if element is input
$('input[id^="id_"]').on('click', function() {
alert(this.id);
});
});
Related
Beginner to all of this, playing around with Firebase. Basically, I want to retrieve text entries from Firebase and have an "Approve" button next to it. When the button is clicked, I want that specific text entry to be pushed to a new Firebase location and the text removed from the page. I am creating the button and the text dynamically and I am having some trouble with selecting the button and the divs I created. I know I have to use on() but I'm unsure of how to use it.
Thanks!
approveRef.on('child_added', function(snapshot) {
var posts = snapshot.val();
$('<div id="post">').text(posts.text).append('<button style ="button" id="approve">Approve</button>').appendTo($('#feed'));
});
$('#approve').on("click", function(){
var text = $('#post').val();
postsRef.push({'text':text});
$('#post').remove();
});
You have to bind .on() on a container of your dynamically added element that is already on the page when you load it, and have it like this:
$('#yourContainer').on('click', '#approve', function(){
//your code here..
});
Your .on() didn't work, because you are adding the button dynamically. You can't find the dynamically added elements directly using that elements id selector like $('#approve'). So you should
bind .on() with $(document) selector. This will always contain your dynamically added elements.
$(document).on( eventName, selector, function(){} );
$(document).on('click','#approve',function(){
//your code here
});
I find a quick dip into the DOM, and then running back into jQuery very handy for this problem:
// Construct some new DOM element.
$(whatever).html('... id="mynewthing"...');
// This won't work...
$("#mynewthing")...
// But this will...
$(document.getElementById("mynewthing"))...
This works by turning the DOM object directly into a selector. I like it because the approach is transparent in operation/intent.
Another alternative, simpler to understand, less powerful, also perfectly valid, is to simply bind the event while you create the element:
approveRef.on('child_added', function(snapshot) {
var posts = snapshot.val();
var $button = $('<button style ="button" id="approve">Approve</button>');
$button.on("click", function(){
var text = $('#post').val();
postsRef.push({'text':text});
$('#post').remove();
});
$('<div id="post">').text(posts.text).append($button).appendTo($('#feed'));
});
Another problem you are going to run into, assuming there will be more than one of these on a page, is that you are using IDs in the records. They're going to clash if they aren't unique.
A great alternative is to refer to these items with data-* tags or other identifying characteristics, such as css tags. But in your case, you don't need them at all!
approveRef.on('child_added', function(snapshot) {
var posts = snapshot.val();
var id = snapshot.name();
var $button = $('<button style="button">Approve</button>');
$button.on("click", function(){
// use parent.closest(...) in place of an ID here!
var text = $(this).parent().closest('textarea').val();
postsRef.push({'text':text});
$(this).parent().remove();
});
/* just an example of how to use a data-* tag; I could now refer to this element using:
$('#feed').find('[data-record="'+id+'"]') if I needed to find it */
$('<div data-record="'+id+'">').text(posts.text).append($button).appendTo($('#feed'));
});
I don't sure exactly what are you looking for. You can use .find() to select dynamically elements. I think .find() will look at the html structure again to get needed elements.
$("#button").click(function(e){
$(".parentContainer").find(".dynamically-child-element").html("Hello world");
});
Or
$(".parentContainer").find(".dynamically-child-element").html("Hello world"); // not in click event
So this is my demo
I have a code where i appending to div some html over JQuery like
$("#divId").append("<div class='click' data-id='id'></div>");
and I want to acces by click appended div like this
$(".click").click(function(){
var id = $(this).attr('data-id');
alert(id);
});
but when I click, nothink happens, is there some solution for this? Thanks!
You need to use event Delegation.
$("body").on('click', '.click', function(){
var id = $(this).attr('data-id');
alert(id);
});
As the events are only bound for already existing elements on the page. but in your case you are dynamically appending the elements.
body can also be substituted to the closest ancestor that contains these elements.
$("#divId").on('click',
Check Fiddle
I have a html div and I clone it using Jquery. That div contains labels and text fields. ids of all of them generated and assigned dynamically. I have no problem with that.
A java script is assigned to a text field of original div. The cloned text fields does not have the javascript assigned to it.
the script I need to assign:
<script>
$(function() {
$("#datepick_onBooking,#datepick_Pay1,#datepick_Pay2,#datepick_totPay,#datepick_deedFees").datepicker();
});
</script>
the script I use to make clones:
<script>
var i = 3;
//When DOM loaded we attach click event to button
$(document).ready(function() {
$('#addAnotherPayment').click(function() {
var cloned = $('.PayDiv0').first().clone();
var noOfDivs = $('.PayDiv0').length+2;
cloned.insertBefore("#totPayForm");
// append count to the ids
cloned.attr('id', 'PayDiv' + noOfDivs);
cloned.find('label').attr('id', 'PayLbl' + noOfDivs);
cloned.find('input[type="text"]').attr('id', 'datepick_Pay'+ noOfDivs);
cloned.find('input[type="number"]').attr('id', 'amount_Pay'+ noOfDivs);
cloned.find('.PayLbl2').html("Payment No " + i++ + ':');
});
});
</script>
datepick_Pay1, datepick_Pay2, datepick_totPay, datepick_deedFees are static elements and they have been assigned to the script. I create text fields using cloning as datepick_Pay3,datepick_Pay4, and so on.
I cannot figure out how to dynamically assign the script to that newly created elements.How can I do that?
A Boolean indicating whether event handlers and data should be copied along with the elements.
change this line.
var cloned = $('.PayDiv0').first().clone(true);
when you clone something especially elements which having events
use parameter as
clone(true)
But this will be harmfull based on how event is attached on the actual element when copying the events to the cloned element may affect the actual.
You need to clone with events. http://api.jquery.com/clone/
var cloned = $('.PayDiv0').first().clone(true);
Then your script needs to be changed to work for dynamic elements. Here as soon as input elements gets focus, asssign the datepicker based on wild card id selector, if it doesn't already have one.
$(function() {
$('body').on('focus',"input[id^=datepick_]", function(){
if(!$(this).hasClass('.hasdatepicker'))
{
$(this).datepicker();
}
});
});
I have a function that calls when the user mouseover a certain div. The function shows a different div, but the issue is that it shows all of the divs with that class.
Here's the JS:
$('.edit-image').mouseover(
function(e){
$('.edit-image-link').show();
});
What I want it to do is only show the .edit-image-link div if it's a child of the element that the user has their mouse over.
You can use .find() to fetch only the descendant elements of an element based on a selector.
$('.edit-image').mouseover(function (e) {
$(this).find('.edit-image-link').show();
});
or you can pass a context to jQuery for searching a selector
$('.edit-image').mouseover(function (e) {
$('.edit-image-link', this).show();
});
Note: Inside a jQuery callback method like event handlers, this will refer the to current dom element
I personally prefer the first method
Use
$('.edit-image').mouseover(function () {
$(this).find('.edit-image-link').show();
});
References
this keyword
.find()
Get the descendants of each element in the current set of matched
elements, filtered by a selector, jQuery object, or element.
I have a couple of drop down boxes with ids country1, country2, ... When the country is changed in a drop down the value of the country shoudl be displayed in an alert box.
if I add the onchange handler for one box like this it works fine:
$('#country1') .live('change', function(e){
var selectedCountry = e.target.options[e.target.selectedIndex].value;
alert(selectedCountry);
});
But I need to do this dynamically for all drop down boxes so I tried:
$(document).ready(function() {
$('[id^=country]') .each(function(key,element){
$(this).live('change', function(e){
var selectedCountry = e.target.options[e.target.selectedIndex].value;
alert(selectedCountry);
});
});
});
This doesn't work. No syntax error but just nothing happens when the seleted country is changed. I am sure that the each loop is performed a couple of times and the array contains the select boxes.
Any idea on that?
Thanks,
Paul
The reason .live() existed was to account for elements not present when you call the selector.
$('[id^=country]') .each(function(key,element){ iterates over elements that have an id that starts with country, but only those that exist when you run the selector. It won't work for elements that you create after you call .each(), so using .live() wouldn't do you much good.
Use the new style event delegation syntax with that selector and it should work:
$(document).on('change', '[id^=country]', function(e) {
// ...
});
Replace document with the closest parent that doesn't get dynamically generated.
Also, consider adding a class to those elements along with the id attribute.
Instead of incremental ids I'd use a class. Then the live method is deprecated but you may use on with delegation on the closest static parent or on document otherwise.
$('#closestStaticParent').on('change', '.country', function() {
// this applies to all current and future .country elements
});
You don't need an each loop this way; plus events are attached to all the elements in the jQuery collection, in this case all .country elements.