Javascript function not called in a dynamically generated page - javascript

I have a web application in which I am generating some HTML content based on the response to an AJAX call. In the HTML, I am creating some links with onclick() event wired to another Javascript function in the same page. But when the page loads and the links are generated in the final rendered HTML output, clicking on the links does not call the bound Javascript function. Am I doing anything wrong here? Can someone help me how to solve this issue?
Here's the Javascript function to generate the HTML code:
function getBotsStatus() {
$.post('/bot/status', {
}).done(function(bots_status) {
all_bots_status = bots_status['bots_status'];
$('#bots_table').html('');
for (var one_job in all_bots_status) {
var text = '';
if (all_bots_status[one_job] == 'running')
text = '<tr><td>' + one_job + '</td><td>' + all_bots_status[one_job] + '</td><td><a href=\'\' onclick=\'postStartBot(\'' + one_job + '\')\'>Start</a></td></tr>';
else if (all_bots_status[one_job] == 'stopped')
text = '<tr><td>' + one_job + '</td><td>' + all_bots_status[one_job] + '</td><td><a href=\'\' onclick=\'postStopBot(\'' + one_job + '\')\'>Start</a></td></tr>';
$('#bots_table').append(text);
}
}).fail(function() {
alert('Error');
});
}

Adding click handler on href for a tag is a bad practice.
You should consider of attaching event handler through on after td/a is created .
change your code to the following
function getBotsStatus() {
$.post('/bot/status', {}).done(function(bots_status) {
all_bots_status = bots_status['bots_status'];
$('#bots_table').html('');
for (var one_job in all_bots_status) {
var text = '';
if (all_bots_status[one_job] == 'running')
text = '<tr><td>' + one_job + '</td><td>' + all_bots_status[one_job] + '</td><td><a >Start</a></td></tr>';
else if (all_bots_status[one_job] == 'stopped')
text = '<tr><td>' + one_job + '</td><td>' + all_bots_status[one_job] + '</td><td><a >Start</a></td></tr>';
$('#bots_table').append(text);
$("$bots_table td").on('click','a',function(){
alert("here");
});
}
}).fail(function() {
alert('Error');
});
}
Hope it helps

You are using single quotes for the onclick and for the functions parameters, making the code invalid. You rendered html looks like this: (by your code)
onclick='postStartBot('JOBID')'
resulting in an invalid code, it should use different quotes for the function and the parameters. Try this:
onclick=\'postStartBot("' + one_job + '")\'
that will render in something like
onclick='postStartBot("JOBID")'
If one_job is numeric you don't need the double quotes either

Related

How to concatenate and pass parameters values in html using jQuery

I'm using jQuery to get values from ajax rest call, I'm trying to concatenate these values into an 'a' tag in order to create a pagination section for my results (picture attached).
I'm sending the HTML (divHTMLPages) but the result is not well-formed and not working, I've tried with double quotes and single but still not well-formed. So, I wonder if this is a good approach to accomplish what I need to create the pagination. The 'a' tag is going to trigger the onclick event with four parameters (query for rest call, department, row limit and the start row for display)
if (_startRow == 0) {
console.log("First page");
var currentPage = 1;
// Set Next Page
var nextPage = 2;
var startRowNextPage = _startRow + _rowLimit + 1;
var query = $('#queryU').val();
// page Link
divHTMLPages = "<strong>1</strong> ";
divHTMLPages += "<a href='#' onclick='getRESTResults(" + query + "', '" + _reg + "', " + _rowLimit + ", " + _startRow + ")>" + nextPage + "</a> ";
console.log("Next page: " + nextPage);
}
Thanks in advance for any help on this.
Pagination
Rather than trying to type out how the function should be called in an HTML string, it would be much more elegant to attach an event listener to the element in question. For example, assuming the parent element you're inserting elements into is called parent, you could do something like this:
const a = document.createElement('a');
a.href = '#';
a.textContent = nextPage;
a.onclick = () => getRESTResults(query, _reg, _rowLimit, _startRow);
parent.appendChild(a);
Once an event listener is attached, like with the onclick above, make sure not to change the innerHTML of the container (like with innerHTML += <something>), because that will corrupt any existing listeners inside the container - instead, append elements explicitly with methods like createElement and appendChild, as shown above, or use insertAdjacentHTML (which does not re-parse the whole container's contents).
$(function()
{
var query=10;
var _reg="12";
var _rowLimit="test";
var _startRow="aa";
var nextPage="testhref";
//before divHTMLPages+=,must be define divHTMLPages value
var divHTMLPages = "<a href='#' onclick=getRESTResults('"+query + "','" + _reg + "','" + _rowLimit + "','" + _startRow + "')>" + nextPage + "</a>";
///or use es6 `` Template literals
var divHTMLPages1 = `` + nextPage + ``;
$("#test").append("<div>"+divHTMLPages+"</div>");
$("#test").append("<div>"+divHTMLPages1+"</div>");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="test"></div>

Passing argument to on click event of dynamically generated element

I am trying to pass arguments to onclick event of dynamically generated element. I have already seen the existing stackoveflow questions but it didn't answer my specific need.In this existing question , they are trying to access data using $(this).text(); but I can't use this in my example.
Click event doesn't work on dynamically generated elements
In below code snippet, I am trying to pass program and macroVal to onclick event but it doesn't work.
onClickTest = function(text, type) {
if(text != ""){
// The HTML that will be returned
var program = this.buffer.program;
var out = "<span class=\"";
out += type + " consolas-text";
if (type === "macro" && program) {
var macroVal = text.substring(1, text.length-1);
out += " macro1 program='" + program + "' macroVal='" + macroVal + "'";
}
out += "\">";
out += text;
out += "</span>";
console.log("out " + out);
$("p").on("click" , "span.macro1" , function(e)
{
BqlUtil.myFunction(program, macroVal);
});
}else{
var out = text;
}
return out;
};
console.log of out give me this
<span class="macro consolas-text macro1 program='test1' macroVal='test2'">{TEST}</span>
I have tried both this.program and program but it doesn't work.
Obtain values of span element attributes, since you include them in html:
$("p").on("click" , "span.macro" , function(e)
{
BqlUtil.myFunction(this.getAttribute("program"),
this.getAttribute("macroVal"));
});
There are, however, several things wrong in your code.
you specify class attribute twice in html assigned to out,
single quotes you use are not correct (use ', not ’),
quotes of attribute values are messed up: consistently use either single or double quotes for attribute values
var out = "<span class='";
...
out += "' class='macro' program='" + program + "' macroVal='" + macroVal + ;
...
out += "'>";
depending on how many times you plan to call onClickTest, you may end up with multiple click event handlers for p span.macro.

jQuery getJSON and get value from button

I'm download data from JSON file and display button with value:
function iterateOverPrzepisy(best) {
$('#listaPrzepisow').html('');
$.getJSON('przepisy.json', function(data) {
for (var x in przepisyDost) {
$('#listaPrzepisow').append(" <div data-role=\"collapsible\"><h2>" + przepisyDost[x].nazwa + "</h2>" +
"<ul data-role=\"listview\" data-theme=\"d\" data-divider-theme=\"d\">" +
"<li>" +
"<h3>Składniki: " + przepisyDost[x].skladniki + "</h3>" +
"<p class='ui-li-desc' style='white-space: pre-wrap; text-align: justify;'>" + przepisyDost[x].tresc + "</p>" +
"<button id='ulubioneBtn' value='" + przepisyDost[x].id + "'>Ulubione</button></li>" +
"</ul>" +
"</div>");
j++;
}
})
}
When I click to button #ulubioneBtn I would like to get value from this button. So I add done to getJSON
}).done(function(data){
$('button#ulubioneBtn').click(function (event) {
console.log("Ulubione: ");
event.preventDefault();
var id = $("button#ulubioneBtn").val();
console.log("Value: " + id);
//dodajemy do ulubionych
localStorage.setItem("ulubione"+id, id);
});
});
But it's not working. When I click on button Ulubione I always get in console log value = 0
The problem seems to be that you add multiple buttons with the same id. An id of a html element should be unique.
przepisyDost does not appear to be defined at
for (var x in przepisyDost) {
? Try
for (var x in data.przepisyDost) {
Duplicate id's are appended to document at
"<button id='ulubioneBtn' value='" + przepisyDost[x].id
+ "'>Ulubione</button></li>" +
within for loop. Try substituting class for id when appending html string to document
"<button class='ulubioneBtn' value='" + data.przepisyDost[x].id
+ "'>Ulubione</button></li>" +
You could use event delegation to attach click event to .ulubioneBtn elements, outside of .done()
$("#listaPrzepisow").on("click", ".ulubioneBtn", function() {
// do stuff
})
I have created a dummy JSON and executed the same JS with a single change.
In onclick handler instead of getting button I am using $(event.target).
And it is working fine.
Please find the fiddle https://jsfiddle.net/85sctcn9/
$('button#ulubioneBtn').click(function (event) {
console.log("Ulubione: ");
event.preventDefault();
var id = $(event.target).val();
console.log("Value: " + id);
//dodajemy do ulubionych
localStorage.setItem("ulubione"+id, id);
});
Seems like first object doesn't have any id value.
Please check JSON response returned from server.
Hope this helps you in solving.

Rebind Mapbox popups after filtering

I've built a Mapbox map that has a fairly involved custom popup structure, including photos and formatting. I'm using a .csv file and omnivore to feed my data, and creating the popup .on ready. I've also got a search box that searches the data using jQuery.
Independently, each one works. The popups load fine, and the search is working. But after filtering using the search thing, I lose the popups.
I've looked at this similar post but nothing suggested seems to be working. I think this has to do with my popup variable being contained inside of the .on ready function. Is there something I'm missing here? Do I need to restructure how the popups are created?
Here's my code:
var featureLayer = L.mapbox.featureLayer().addTo(map);
jQuery('#search').keyup(search);
Load data, format popups:
var csvLayer = omnivore.csv('Stats.csv', null, L.mapbox.featureLayer())
.on('ready', function() {
map.fitBounds(csvLayer.getBounds(), {paddingTopLeft: [0,25]});
function updownFormat(updown, change){
if (updown === '—') {
return "No change ";
} else if (updown === "N/A") {
return "New store - no data ";
} else if (updown === '▲') {
return '<span class="upPercent">' + updown + "</span> " + change;
} else {
return '<span class="downPercent">' + updown + "</span> " + change;
}
};
csvLayer.eachLayer(function(layer) {
var prop = layer.feature.properties
var popup = '<div class="popup"><h3>'+ prop.storename +'<\/h3>' +
'<h4>'+ prop.town +'</h4>' +
'<p><b>Rank:</b> #'+ prop.rank +' (of 80 stores) <br>' +
'<b>Sales: </b>' + prop.money14 +' (2014)<br>' +
'<b>Growth: </b>' + updownFormat(prop.updown, prop.change) + ' (from 2013)</p>' +
'<h5>Best selling bottles (2014)</h5>' +
'<img src="'+ prop.pop1img +'" class="liquorimg">' +
'<ol><li><b>'+prop.pop1+'</b></li><li>'+prop.pop2+'</li><li>'+prop.pop3+'</li><li>'+prop.pop4+'</li><li>'+prop.pop5+'</li></ol></div>';
layer.bindPopup(popup);
});
})
.addTo(map);
The search function:
function search() {
// get the value of the search input field
var searchString = jQuery('#search').val().toLowerCase();
csvLayer.setFilter(showStoreTown);
function showStoreTown(feature) {
return feature.properties.storetown
.toLowerCase()
.indexOf(searchString) !== -1;
}
}
Fixed, thanks to Twitter! Setting map bounds on "ready" and setting the popup creation on "addlayer" took care of it.

Javascript Parameter Passing Not Working

The code dynamically creates a listview which works but i want to make it so when a listview item is clicked it sends the a url paramater to another method. When i set a paramater it doesnt alert the paramater, but when i give no parameter it works.
var output =
"<li onclick='openURL()'><h3> Module Code: " +
results.rows.item(i).module
+ "</h3>Room: "
+ results.rows.item(i).room +
"</li>";
The above works - No parameter in openURL();
var output =
"<li onclick='openURL('" + results.rows.item(i).url + "')'><h3> Module Code: " +
results.rows.item(i).module
+ "</h3>Room: "
+ results.rows.item(i).room +
"</li>";
The above doesnt work - I have done alert(results.rows.item(i).url) and it has a value.
function openURL(url) {
alert("opening url " + url);
}
Could someone explain what i'm doing wrong, i've been trying to solve the problem for hours.
Cheers!
You are using single quotes to open the HTML attribute, you can't use it as JavaScript String because you'll be closing the HTML attribute, use double quotes:
var output =
"<li onclick='openURL(\"" + results.rows.item(i).url + "\")'><h3> Module Code: " +
results.rows.item(i).module
+ "</h3>Room: "
+ results.rows.item(i).room +
"</li>";

Categories