JQuery: Selecting dynamically created elements and pushing to Firebase
Asked Answered
N

5

21

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();

});
Nanny answered 10/7, 2013 at 1:53 Comment(0)
C
42

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..
});
Creolacreole answered 10/7, 2013 at 1:59 Comment(3)
To expand, the first argument to on() is the event, the second is a "selector" which, if present, delegates the events to children of this element, even if they are added in the futureArcherfish
This worked for me after spending 3+ hours looking for this hack! You sir deserve a medal!Creekmore
Now, how do you do that if you have a bunch of links, and you need to .each them?Litton
R
16

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
});
Regress answered 22/8, 2017 at 5:1 Comment(0)
W
5

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.

Wimer answered 1/7, 2019 at 13:40 Comment(1)
$(document.getElementById("mynewthing"))... with capital iGastric
A
2

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'));
});
Archerfish answered 10/7, 2013 at 2:27 Comment(1)
I don't agree that this is simpler to understand, and it seems unnecessarily complex when binding the .on() command correctly will work just fine.Marseilles
W
1

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

Waxwork answered 8/4, 2020 at 19:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.