Dynamically generate table using Jquery - javascript

I use JQuery version 1.8.4 and jquery-ui-1.9.2
I have this array:
window.mapData.Layers = [{id:1,Title:water}{id:2,Title:land}{id:4,Title:data}{id:1,Title:info}]
I try to create table with some text and two buttons.
Each row in table have to display title the property of object from Layers array
and two buttons edit and delete.Each button have to sent as parameter the id of the property to handler when it clicked.
Here is the code:
(function () {
var content = $('<table>')
$(window.mapData.Layers).each(function (i, j) {
content += '<tr><td>' + j.Title + '</td><td>' + $('<button/>')
.text('Edit').onClick('eventHandler').params('j.id') +'</td>'+'<td>'+$('<button/>').text('Delete').onClick('eventHandler').params('j.id')+'</td>'+'</td></tr>'})
$('#vectorLayerslist').append(content);
}())
Here is result that I get:
water [object Object] [object Object]
land [object Object] [object Object]
data [object Object] [object Object]
info [object Object] [object Object]
But it's not works.As you can see above it's generate only text but not buttons.
Any idea why buttons not generated? If there is any more elegant way to achieve my task?

Build the table as string, then append the string once.
Make use of jQuery's event propagation for dynamically created elements.
var Layers = [{id:1,Title:'water'},{id:2,Title:'land'},{id:4,Title:'data'},{id:5,Title:'info'}];
var vectorLayersList = $('#vectorLayerslist');
// build the table
var content = '<table>';
content += '<thead><tr>';
content += '<th>Title</th>';
content += '<th colspan="2">Actions</th>';
content += '</tr></thead><tbody>';
$.each(Layers, function () {
// we'll store the ID in HTML5 data-attribute for later
content += '<tr data-id="' + this.id + '">';
content += '<td>' + this.Title + '</td>';
// give classes to your buttons for later
content += '<td><button type="button" class="edit">Edit</button></td>';
content += '<td><button type="button" class="delete">Delete</button></td>';
content += '</tr>';
});
content += '</tbody></table>';
// append the table once
vectorLayersList.append(content);
// attach event handlers
vectorLayersList.on('click', '.edit', function () {
var id = $(this).closest('tr').data('id');
console.log('editing ' + id);
});
vectorLayersList.on('click', '.delete', function () {
var id = $(this).closest('tr').data('id');
console.log('deleting ' + id);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="vectorLayerslist"></div>

Related

Why variable is undefined inside foreach function?

I have this jQuery function were I create a table:
function propertyView(values) {
// build the table
var frame = '<fieldset id = "propertiesValueArea" style="border: solid 1px #6b6b6b;">';
var content = frame + smallHeader + '<table data-role="table" id="propertiesList"><thead><tr></tr></thead>';
$.each($(values), function () {
var data1 = this.RealValue.FieldValue;
var data2 = this.RealValue.Id;
//create tables row
content += '<tr data-id=' + this.Id + '>';
content += '<td style="vertical-align: inherit;text-align:center;"><label for="">' + this.FieldName + '</label></td>';
if (this.FieldValue.indexOf(',') > -1) {
content += '<td style="text-align:center;"><select>';
this.FieldValue.split(',').forEach(function (item) {
if (data1 === item) //Here data1 is undefined!!!
{
content += '<option selected="selected" value="">' + item + '</option>';
}
else {
content += '<option value="">' + item + '</option>';
}
})
content += '</select></td>';
}
else {
content += '<td style="text-align:center;"><input type="text" id="propFieldName" data-id="' + this.Id + '" value="' + congiValue(this.FieldValue, this.RealValue) + '"/>';
}
content += '</tr>';
});
content += '</table>';
content += '</fieldset>'
return content;
}
Inside outter each function I create 2 variables:
var data1 = this.RealValue.FieldValue;
var data2 = this.RealValue.Id;
I try to create this variable inside inner each:
if (data1 === item) //Here data1 is undefined!!!
But on this row I get this error:
Uncaught ReferenceError: data1 is not defined
Any idea why data1 is undefined?
It can be undefined only because this.RealValue.FieldValue or this.RealValue is undefined
It looks like
var data1 = this.RealValue.FieldValue; //it's value is undefined
this.FieldValue //it's value is undefined
try to
console.log(this.FieldValue)
console.log(data1)
After that you can easily found where you are getting an error and why. Else everything looks fine with your code.
I have encountered similar problem before. It took me several hours to discover the problem. Now that aside there some things which is not clear here.
is the value coming from another function's operation? If
this.RealValue.FieldValue;
is coming from e.g. a result of maybe another function then you would need to use async/await to ensure that the function completes its operation and there is data in this.RealValue.FieldValue before you move on to the next line of code.
Maybe the this.RealValue.FieldValue itself does not have any thing assigned to it outside of the function itself.
In order to help you we would need a complete code. If you think your code is too private then you can go through it by trying what #Negi Rox said earlier.
Put console.log(this.RealValue.FieldValue) at various strategic locations in your code to determine when it was assigned a value.

Adding onclick event on dynamically created HTML caused an error: Uncaught SyntaxError: Unexpected identifier

I'm using ajax to get an results from code behind, when I Get those results I'm creating an a divs. And this works fine, adding a div dynamically.
Now I Want to add on each div onclick event which should raise some method when it's clicked, so here is my full code:
<script>
function onSelectGroup(Id) {
$.ajax({
method: "GET",
url: "Product/GetProductsByGroupId",
data: { groupId: Id }
})
.done(function (response) {
$(".products").html("");
for (var i = 0; i < response.length; i++) {
//I wrote onclick = "addProduct(response[i])" to generate for each div each onclick event
let item = '<div class="col-md-3"> <div class="Product-holder" onclick="addProduct(' + response[i] + ')" id=' + response[i].ProductId + '><img class="img-responsive" src="images/maxresdefault.jpg"><p class="product-title" style="color:white;margin-top:5px;text-align:center;"> ' + response[i].Title + '</p></div></div>';
//Trying to append it to my .product class because it's parent of this divs above
$(".products").append(item);
}})};
function addProduct(product) {
console.log(product.Title);
}
</script>
But when I click on any of my generated divs I get an following error:
Uncaught SyntaxError: Unexpected identifier
I'm looking for issue for 3h allready, and I'm really stucked here..
Any kind of help would be great.
Thanks
P.S
CODE BEHIND - C # METHOD:
public ActionResult GetProductsByGroupId(int groupId)
{
var products = ProductController.GetProductsByGroupId(groupId);
if(products)
{
List<Product> productlist = new List<Product>();
foreach (var item in products)
{
Product product = new Product();
product.ProductId = Convert.ToInt32(item.Id);
product.Price = Convert.ToDecimal(item.Price);
product.Title = item.Title;
productlist.Add(product);
}
return Json(productlist, JsonRequestBehavior.AllowGet);
}
return Json(products, JsonRequestBehavior.AllowGet);
}
Remove the onclick and use delegate, you are passing an object to a function which convert response[i] to text [Object object], use data-* attributes to hold data for each object and attach an event to the div with the class product, on click of the div we'll use $(this) to reference the current clicked div and access its data attributes.
$(".products").html("");
var response = [{ProductId:4, Title:"Doe", Price: 34.89}, {ProductId:6, Title:"Jane", Price: 20.99}];
for (var i = 0; i < response.length; i++) {
//I wrote onclick = "addProduct(response[i])" to generate for each div each onclick event
let item = '<div class="col-md-3"> <div class="Product-holder product" data-price="'+ response[i].Price +'" data-title="' + response[i].Title + '" id=' + response[i].ProductId + '><img class="img-responsive" src="images/maxresdefault.jpg"><p class="product-title" style="color:white;margin-top:5px;text-align:center;"> ' + response[i].Title + '</p></div></div>';
//Trying to append it to my .product class because it's parent of this divs above
$(".products").append(item);
//console.log(item);
};
$(document).on('click', '.product', function(){
var product = {Title: $(this).data('title'), ProductId: $(this).attr('id'), Price: $(this).data('price')};
console.log(product);
// here use ajax to add this product
});
body {
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="products"></div>
Take a look at the Delegate jquery method!
Description: Attach a handler to one or more events for all elements that match the selector, now or in the future, based on a specific set of root elements.
So you basically need to bind the onClick event to the parent div, and pass a selector that will appear later on the child divs.
<script>
function onSelectGroup(Id) {
$.ajax(
//Do your ajax call here
).done(function (response) {
for (var i = 0; i < response.length; i++) {
let item = '<div class="event-target"></div>'
$(".products").append(item);
}})};
// Here's where the magic happens.
// We bind the event to the elements that have the 'event-target' class
//inside the element that have the 'products' class.
$('.products').on('click', '.event-target', function(){
console.log(this);
})
</script>
Warning: take care using delegate, if you use the wrong selector you can end up triggering the event for each element on the page, or even recursivelly (belive me, have made it a lot...)
Use data attributes to store any data & on click retrieve the data attribute.The code is not tested but hopefully it will work
let item = '<div class="col-md-3">' +
' <div class="Product-holder" ' +
'onclick="addProduct(this)"' +
' data-title="'+response[i].Title+'"' +
' id=' + response[i].ProductId + '>' +
'<img class="img-responsive" src="images/maxresdefault.jpg">' +
'<p class="product-title" style="color:white;margin-top:5px;text-align:center;"> ' + response[i].Title + '</p>' +
'</div>' +
'</div>';
$(".products").append(item);
function addProduct(product) {
console.log($(product).data('title'));
}
Also you need to delegate the event since they are dynamically created element
$("body").on("click",".Product-holder",function(){
console.log($(product).data('title'));
})
In this case the inline event handler that is onclick function will be redundant
Let me going to explant your code.
for (var i = 0; i < response.length; i++) {
let item = '<div class="col-md-3"> <div class="Product-holder" onclick="addProduct(' + response[i] + ')" id=' + response[i].ProductId + '><img class="img-responsive" src="images/maxresdefault.jpg"><p class="product-title" style="color:white;margin-top:5px;text-align:center;"> ' + response[i].Title + '</p></div></div>';
$(".products").append(item);
}})};
On these line of code, I saw that you have added strings to a variable.
but more exception response[i].ProductId seem like response[i] was an object.
but in Javascript you can't add an object to String by + operator, it will be return "string [object] string". What is solution for that??
Convert your object to JSON String like {"id": 123, "name": "Product name"}, that will show in html code like this onclick='addProduct({"id": 123, "name": "Product name"})' remember that onclick = ' not "

How to concat html object to html string using jquery?

I have created a loop and below is the part of the code between that loop
--- Loop Starts ---
var aElement = $('<a>');
aElement.attr('href', '#');
aElement.text(title);
aElement.click(function() {
alert("Hello World);
});
video_list_html += '<tr>' +
'<th scope="row">' + count + '</th>' +
'<td>' + aElement + '</td>' +
'</tr>';
--- Loop Starts ---
But as aElement is an object, it doesn't attach as html tag to the video_list_html but it attaches like this
[object Object]
How do I fix this, so that it attaches inside the video_list_html and also the .click() event stay working.
Try using aElement[0].outerHTML instead of aElement. Leave click handler as is.
The issue is because you cannot append an object to a string. The object gets coerced, ans the result is, as you've seen, [Object object].
A better solution to this problem would be to append the new HTML as one entire string, then use a delegated event handler to catch the events from those dynamically added elements. Try this:
var data = [{
videoId: 'abc123',
title: 'Video #1'
}, {
videoId: 'xyz987',
title: 'Video #2'
}]
var video_list_html = data.map(function(o, i) {
return '<tr><th scope="row">' + i + '</th><td>' + o.title + '</td></tr>';
}).join('');
$('#yourTable').append(video_list_html).on('click', 'a', function(e) {
e.preventDefault();
console.log($(this).data('videoid'));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="yourTable"></table>

how to put a button inside div where data is filled dynamically through $.each function

This should be very simple but i am struggling here.
I have a parent div which have multiple child div. These child div are generated according to $.each() function. Number of times function run, num of div get generated.Now, i want to write a server side function on button click but i am unable to list that button in these child div.
<div class="div1">
<div class="div2">
// this is the button which i cant see in my div2 div
<button type="input">follow</button>
<script type="text/javascript">
$(document).ready(function() {
$.getJSON("/Home/GetUsers", null, function(data) {
$(".div1").html("");
$.each(data, function(i, item) {
var html = "<div class='div2'>";
html += "Name: " + item.UserName + "<br />";
html += item.ArticleCount;
html += "<img src='" + item.UserImage + "'height='20px' width='20px'/>"
html += "</div>";
$(".div1").append(html);
});
});
});
</script>
</div>
</div>
Any type of guidance appreciated.
If you'd like to add a button per child div you can do it in this way:
$(document).ready(function() {
var parent = $(".div1");
$.getJSON("/Home/GetUsers", null, function(data) {
parent.html("");
$.each(data, function(i, item) {
var html = "<div class='div2'>";
html += "Name: " + item.UserName + "<br />";
html += item.ArticleCount;
html += "<img src='" + item.UserImage + "'height='20px' width='20px'/>";
html += "<button type='button' class='newButton'>Click Me!</button>";
html += "</div>";
parent.append(html);
});
});
// In order to ensure that the button click is handled no matter when it was
// added, we can delegate the handler to the parent.
parent.on('click', '.newButton', function(e) {
var button = $(this);
// Handle the individual button click server side call here.
});
});

how to refresh the list in jquery javascript

Hi i m having one page with one textbox named search and one search button. When i'm searching anything for the first time it's showing me the right data but when i'm searching some other things for the next time then the elements which was listed before are also appended below of that new list. Suppose i'm searching state name by k it will give me right list of karnataka, kerala. But if i start to search again by g, it will show me in output as goa,gujrat,karnataka kerala. i tried using refresh option but it still not working. This is my js code
$.each(response.state, function (i, state) {
$('#statelist').append(
'<li>' +
'<a href="#">'
+
+'<b>'+ '<font color="green">'+'<h3>'+ state.Name +'</h3>'+'</font>' +'</b>'+
'</a>' +
'</li>'
);
});
$('li img').width(100);
$('.ui-li-icon li').click(function() {
var index = $(this).index();
text = $(this).text();
// alert('Index is: ' + index + ' and text is ' + text);
});
$("#statelist").listview("refresh");
and this is html
You are using .append() function. It appends whatever you append to the end of the list.
Check this link:
http://api.jquery.com/append/
Try using innerHTML property of the DOM model.
You could add
If(!('#statelist').html() == ""){
$(this).remove();
//execute rest of code that appends state list
}
Then do an else statement and execute your append code without removing()
UPDATE: a better option is to do this-
$.each(response.state, function (i, state) {
$('#statelist').html(
'<li>' +
'<a href="#">'
+
+'<b>'+ '<font color="green">'+'<h3>'+ state.Name +'</h3>'+'</font>' +'</b>'+
'</a>' +
'</li>'
);
});
$('li img').width(100);
$('.ui-li-icon li').click(function() {
var index = $(this).index();
text = $(this).text();
// alert('Index is: ' + index + ' and text is ' + text);
});

Categories

Resources