Get data of dynamically added elements using JQuery - javascript

Very similar problem to Dynamically added HTML elements can't be found using jQuery but, I want to access new element's data and not its event.
The element is added by JQuery through AJAX request. It is not missing to the DOM when I try to access it.
<button id="get-data">Get data</button>
<div id="container">
<!-- everything here is added through the first ajax call -->
<button id="update-data">Update</button>
<input type="hidden" id="elem" data-data="someData" />
</div>
So I tried :
$('#elem').data('data');
$(this).parents().find('#elem').data('data');
$(document).find('#elem').data('data');
...with no success.
And it's not going to work : JQuery doesn't find #elem in the DOM :
console.log($('input'));
// OR
console.log($(document).find('input'));
...output a list of the input items in the DOM, but #elem is not in this list.
I'm guessing that I can't use $().find() nor the direct $() to get dynamically added content, so how to I get it ?
Here is how my JS is organized :
$(function() {
$('#get-data').click(function() {
$.ajax({
url: "/"
}).done(function() {
$('#container').html(ajaxResult)
});
});
$(document).on('click', '#update-data', function() {
$.ajax({
url: "/new",
data: $('#elem').data('data')
});
//This ajax call doesn't work as expected because data is missing.
//#update-data is inserted by the first AJAX call, but the click even is catched without any problem here.
});
});
Edit after further research:
I tried to output the result of different JQuery selectors :
$('#container').find('#elem');
JQuery Object (length: 0) => prevObject : [ input#elem ]
$('#container').find('#elem').first();
JQuery Object (length: 0) => prevObject : JQuery Object (length: 0) => prevObject : [ input#elem ]
$('#elem');
//or
$(document).find('#elem');
//or
$('#container #elem');
JQueryObject (length: 0) => prevObject : [ HTMLDocument my_website.com ]
$('#elem').first();
//or
$(document).find('#elem').first();
//or
$('#container #elem').first();
JQuery Object (length: 0) => prevObject : JQuery Object (length: 0) => prevObject : [ HTMLDocument my_website.com ]

I have this working when I use the hidden selector. They both work below:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
<div class="row">
<div class="col">
<button id="get-data">Get data</button>
<div id="container">
<!-- everything here is added through the first ajax call -->
<button id="update-data">Update</button>
<button id="find-element">Find</button>
<input type="hidden" id="elem" data-data="someData" />
</div>
</div>
</div>
<script type="text/javascript">
$(document).ready(function () {
$('#find-element').bind("click", function () {
// your statements;
var boo = $('#elem').data('data');
var foo = $("#elem:hidden").data('data');
alert(boo + "\n" + foo);
});
});
</script>

Related

How do I access the list element that is appended after html was created

I am adding a list element using the append function in jQuery, how do I reference this on my onclick function? Below is my code
$(function() {
let $movies = $('#showList')
let $m = $('#show')
$.ajax({
method: 'GET',
url: 'http://api.tvmaze.com/shows',
success: function(movies) {
$.each(movies, function(i, movie) {
$movies.append('<li id="list">' + movie.name + '</li>')
})
}
})
});
$('#list').on('click', 'a', function(event) {
console.log('here');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<h1 id='bruh'>TV Shows</h1>
<ul id="showList"></ul>
<div id="show"></div>
<form id="searchForm">
<input type="text" id="search_term">
<label for="text">Search</label>
<button>Submit</button>
</form>
<a id="homelink" href="#" hidden>Back to All Shows</a>
There is no message in console when I click on the link.
The attribute id should unique in a document, you can use class instead.
Try $('body').on('click', '.list a', function(event){....
Demo:
$(function() {
let $movies = $('#showList')
let $m = $('#show')
$.ajax({
method: 'GET',
url: 'http://api.tvmaze.com/shows',
success: function(movies) {
$.each(movies, function(i, movie) {
$movies.append('<li class="list">' + movie.name + '</li>')
})
}
})
});
$('body').on('click', '.list a', function(event) {
console.log('here');
event.preventDefault();//stay on the same page
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<h1 id='bruh'>TV Shows</h1>
<ul id="showList"></ul>
<div id="show"></div>
<form id="searchForm">
<input type="text" id="search_term">
<label for="text">Search</label>
<button>Submit</button>
</form>
<a id="homelink" href="#" hidden>Back to All Shows</a>
You can give the appended divs a class then call them by it like this :
$movies.append('<li class="movie" id="list">'+ movie.name +'</li>');
//then later
let movies = $('.movie');
console.log(movies);
but if you meant to execute this script right after the ajax request
then you should call a function in the ajax success since ajax is async and the moment you execute a jquery select , the elements are still not there because ajax takes more time to retrieve the data put it in the document...
you can make a getMovies() to execute there like this:
//declare this outside the ajax
let movies = []
function getMovies(){
return $('.movie');
}
then
//ajax
success: function(){
movies = getMovies(); //add this line
}
there you go now you have movies stocked inside the 'movies' array
It seems you are running into a race condition of sorts. You are building the list using an asynchronous ajax request to an API. Before that completes, you are then attaching the Javascript code to trigger an event.
What you need to do is add the callback inside of the ready block after the list data is retrieved and the list is created.

Add class/text to a jQuery element

I'm trying to clone the following HTML template and add class/text to it.
<template id="result">
<section>
<div class="alert">
<p class="someText"></p>
</div>
</section>
</template>
So the user first submits a question:
<div id="answer"></div>
<section class="row">
<form id="form" action="/" method="GET">
<div>
<input id="question" />
</div>
</form>
</section>
Then the script executes:
$(document).ready(function () {
$('#form').on('submit', function (event) {
$.ajax({
data: {...},
type: 'GET',
url: '/result'
}).done(myFunction);
});
});
And finally it clones the template (ID #result), add a class to the element containing a class alert and add some text to the element containing a class someText, and appends it to the element containing ID #answer.
function myFunction(result) {
clone = $('#result').clone();
$('.alert', clone).addClass('myClass');
$('.someText', clone).text('myText');
clone.appendTo("#answer");
}
The function executes (I added a console.log() to the end of it to be sure) but nothing is appending.
Consider the following.
function create_message(result) {
var section = $("#result").children().clone();
$('.alert', section).addClass(result.status);
$('.address', section).text(result.address);
$('.extract', section).text(result.extract);
$('.question', section).text(result.question);
section.appendTo("#answer");
}
This creates a clone of all the HTML Elements inside the Template with ID result. It then finds specific classes inside the Object section and makes changes.
You can also do the following.
section.find(".alert").addClass(result.status);
See more: https://api.jquery.com/clone/
Update
Use <template> to hold some content that will be hidden...
So if you Clone the Template and append it, it will still be hidden.
Try the following:
function myFunction(result) {
clone = $('#result > section').clone();
$('.alert', clone).addClass('myClass');
$('.someText', clone).text('myText');
clone.appendTo("#answer");
}
Update 2
I don't use <template>, so I had to re-read some stuff. It has a content portion, so it has an HTML Fragment contained within and is not like other HTML Elements, more like an iFrame. So we need to collect the content versus cloning it.
See: How to use HTML template tag with jQuery?
Here is a working example: https://jsfiddle.net/Twisty/rpd9h0mf/20/
Your code will be something more like the following.
JavaScript
$(function() {
function showResults(results) {
var clone = $($('#result').html());
$('.alert', clone).addClass(results.class);
$('.someText', clone).text(results.answer);
clone.appendTo("#answer");
}
$('#question-form').submit(function(event) {
event.preventDefault();
$.ajax({
data: {
q: $("#question").val()
},
type: 'GET',
url: '/result',
success: showResults
});
});
});
This creates a new jQuery Object based on the HTML Content of the Template. Now you can properly edit it and append it.

jQuery - on load of element with ajax

I searched for some time but could not find a working solution for my problem (sorry if I searched wrongly)...
I would like to have the equivalent of the following function for an element loaded with ajax:
$(document).ready(function() {
$('.div-modal-text').css("background-color","red");
});
Therefore I am using the following code:
$('#parent_id').on('action', '#id or class to be born', function to be performed() );
In my example the parent-child structure is: #projectModals (div whose content is dynamically loaded)>...>.div-project-description>.div-modal-text
This translates into the following code in my example:
$('#projectModals').on('load', '.div-project-description', function() {
$(this).find('.div-modal-text').each(function() {
$(this).css("background-color","red");
});
});
I know 'load' does not work with .on(), but I tried different alternatives and I could not find anything working.
Thanks for your help!
EDIT: Here is my (simplified) HTML code:
<div id="projectModals"></div>
content loaded in #projectModals with Ajax:
<div class="row">
<div class="div-project-idcard">
column 1, don't bother too much about this column
</div>
<div class="div-project-description">
<div id="summary" class="div-modal-text">
Column2, text 1
</div>
<div id="purpose" class="div-modal-text"">
Column2, text 2
</div>
<div id="reforestation" class="div-modal-text">
Column2, text 3
</div>
<div id="certification" class="div-modal-text">
Column2, text 4
</div>
</div>
</div>
If you're waiting for it to be loaded via ajax, consider using $(window).ajaxSuccess() instead:
$(window).ajaxSuccess(function(){
$('#projectModals .div-project-description .div-modal-text').each(function() {
$(this).css("background-color","red");
});
});
for what I understand, you want to change some background color after an ajax has been executed.
I think it's best to make the operation in the ajax success
$.ajax({
url: "some url",
data: {some data},
success: onAjaxSuccess,
});
and then;
function onAjaxSuccess(data){
//.. do things with data
var toExecute = $('#projectModals .div-project-description');
toExecute.find('.div-modal-text').each(function() {
$(this).css("background-color","red");
});
}

Why i can't append some html in to the desired element?

i hope someone can lend me a hand, i have been trying to insert some code via .post using jquery everything seem to works fine but the response data doesn't insert on the conhere div
html
<div class="ui-grid-a">
<div class="ui-block-a main">
<div data-role="fieldcontain">
<input type="checkbox" value="1##2##2##1080|2" name="pro1" id="pro1" class="checkpro">
<label for="pro1"> product description
</label>
</div>
</div>
<div class="ui-block-b side">
<div class="conhere">
</div>
</div>
</div>
javascript
$( document ).on( "change",".checkpro", function(event, ui) {
var checkedpro = $(this).is(':checked')?1:0;
if (checkedpro==1){
var variable=$(this).val().split("##");
$.post("product.php", h{row :contenedor[0],
mul : variable[1],
can : variable[2],
pri: variable[3],
id : variable[4]},
function(data){
$(this).parents(".ui-grid-a").find(".conhere").empty().append(data).trigger('create');
});
else{
$(this).parents(".ui-grid-a").find(".conhere").empty();
}
There are two issues, both with this code:
$(this).parents(".ui-block-a").find(".conhere")...
The first issue is that the .conhere element doesn't exist within .ui-block-a. It exists in .ui-block-b. (And both .ui-block-a and .ui-block-b are within .ui-grid-a.) find only looks at descendant elements of the elements in the set where it's called.
The second issue is that this is no longer what it was outside the call to $.post. So we want to capture it in a variable we close over.
Finally, in this case I would use closest, not parents:
$(this).closest(".ui-grid-a").find(".ui-block-b .conhere")...
// or
$(this).closest(".ui-grid-a").find(".conhere")...
Combining the above:
$(document).on("change", ".checkpro", function (event, ui) {
var $elm = $(this), // <== Remember $(this)
checkedpro = $elm.is(':checked') ? 1 : 0;
if (checkedpro == 1) {
var variable = $elm.val().split("##");
$.post("product.php", h {
row: contenedor[0],
mul: variable[1],
can: variable[2],
pri: variable[3],
id: variable[4]
},
function (data) {
// v-------------------------------- use it, and note 'closest'
$elm.closest(".ui-grid-a").find(".conhere").empty().append(data).trigger('create');
});
} // <== This } was also missing
else {
$elm.closest(".ui-grid-a").find(".conhere").empty();
}

How do you apply an item, from a list of results, to the parent Div tag for the current object?

I am trying to build a function for inserting the number of Facebook Likes into a Div tag. So far, I have a script that can get the URL from a Div tag which is inside of another Div tag called 'entry' and then have the .getJSON() method retrieve the number of Facebook likes for each entry.However, I can't get each retrieved value of Facebook Likes to insert into a Div tag for each entry. Please note, I simplified my code to where it alerts each Facebook Like value. This is what I have so far:
<div class="entry">
<div class="fburl">https://graph.facebook.com/zombies</div>
<div class="facebook-likes"></div>
</div>
<div class="entry">
<div class="fburl">https://graph.facebook.com/starwars</div>
<div class="facebook-likes"></div>
</div>
And here's my jQuery:
$(document).ready(function(){
$(".entry").each(function() {
var fbURL = $(this).find(".fburl").html();
$.getJSON(fbURL, function(fbData) {
var fbArr = fbData['likes'];
alert(fbArr);
});
});
});
​So what I am trying to do is iterate through each entry, get the Open Graph URL for it, retrieve the Likes value, and then insert it into the appropriate Div tag, so the code should render as:
<div class="entry">
<div class="fburl">https://graph.facebook.com/zombies</div>
<div class="facebook-likes">2,586 Likes</div>
</div>
<div class="entry">
<div class="fburl">https://graph.facebook.com/starwars</div>
<div class="facebook-likes">8,905,721 Likes</div>
</div>
​
​
$(document).ready(function() {
$('.entry').each(function() {
var $this = $(this),
fbURL = $this.children('.fburl').html();
$.getJSON(fbURL, function(fbData) {
$this.children('.facebook-likes').html(fbData['likes'] + ' Likes')
});
});
});
See: http://api.jquery.com/children
Demo: http://jsfiddle.net/9EALz/2/
Note: Using children() is going to be marginally more efficient than using find() as it limits the DOM traversal to a single level ( http://jsperf.com/find-vs-children/13 ). Cashing the jQuery object $(this) via var $this = $(this) is also slightly more efficient as it prevents unnecessary selector interpretation ( http://jsperf.com/jquery-cache-vs-no-chace ).
You may want this
$(document).ready(function(){
$(".entry").each(function() {
var entry=$(this), fbURL=$(".fburl", entry).html(),
el=$('.facebook-likes', entry);
$.getJSON(fbURL, function(fbData) {
el.html(numberWithCommas(fbData['likes'])+" Likes");
});
});
});​
A thousand separator function from here
function numberWithCommas(x) {
return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
}
DEMO.
Update:
Alternatively you can use this too (using data-attribute) without an extra div for fburl, i.e.
<div class="entry">
<div data-fburl="https://graph.facebook.com/zombies" class="facebook-likes"></div>
</div>
JS
$(".entry").each(function() {
var entry=$(this), fbURL = $(".facebook-likes", entry).attr('data-fburl'),
el=$('.facebook-likes', entry);
$.getJSON(fbURL, function(fbData) {
el.html(numberWithCommas(fbData['likes'])+" Likes");
});
});

Categories

Resources