Getting undefined when trying to fetch an ID from a data attribute - javascript

I can't figure out why am I getting undefined when trying to console.outthe iUsedId variable from the code below.
Here I attatch the user id to data-iUserId.
var aUsers = [];
for( var i = 0; i < aUsers.length; i++ ){
$("#lblUsers").append('<tr><th scope="row">'+aUsers[i].id+'</th><td>'+aUsers[i].username+'</td><td>'+aUsers[i].firstName+'</td><td>'+aUsers[i].lastName+'</td><td>'+aUsers[i].email+'</td><td>'+"<span data-iUserId='"+aUsers[i].id+"'</span><input type='checkbox' id='chk_"+i+"'"+'</td></tr>');
}
And here I am trying to use the data from the data attribute, but in the console all I get is undefined.
$(document).ready(function() {
$("#remove").on("click", function() {
$('input:checked').each(function() {
$(this).closest('tr').remove();
var iUserId = $(this).attr('data-iUserId');
console.log(iUserId);
for (var i = 0; i < aUsers.length; i++) {
if (iUserId == aUsers[i].iUsersId) {
aUsers.splice(i, 1);
}
}
});
});
});
Any gueses? Please help!

You are deleting the parent with the containers, then trying to access the element.
removing the parent should be in the last step:
$(document).ready(function() {
$("#remove").on("click", function() {
$('input:checked').each(function() {
var iUserId = $(this).closest('span').attr('data-iUserId');
console.log(iUserId);
for (var i = 0; i < aUsers.length; i++) {
if (iUserId == aUsers[i].iUsersId) {
aUsers.splice(i, 1);
}
}
$(this).closest('tr').remove();
});
});
});
Also, consider the comment of #pBuch

The reason is you are looping over the checkboxes and not the span's which have the attribute you are trying to access.
$(this) refers to the checkbox and not the span in the each method you are using:
$('input:checked').each(function() {
// Inside this each statement $(this) refers
// to the the current 'input:checked' element being accessed
});
You should put the data-iUserId attribute on the checkbox since you are accessing that element.
Also! You are missing the closing '>' on the opening span tag:
<span data-iUserId='"+aUsers[i].id+"'</span>

var aUsers = [];
//...somehow populate array...
// We have to assume here that the array got populated
for (var i = 0; i < aUsers.length; i++) {
$("#lblUsers").append('<tr><th scope="row">' + aUsers[i].id + '</th><td>' + aUsers[i].username + '</td><td>' + aUsers[i].firstName + '</td><td>' + aUsers[i].lastName + '</td><td>' + aUsers[i].email + '</td><td>' + "<span data-iUserId='" + aUsers[i].id + "'></span><input type='checkbox' id='chk_" + i + "'" + '</td></tr>');
}
$(document).ready(function() {
$("#remove").on("click", function() {
$("#lblUsers").find('input[type="checkbox"]:checked').each(function() {
// fixed to get the element with the data
var iUserId = $(this).siblings('[data-iUserId]').data('iuserid');
console.log(iUserId);
for (var i = 0; i < aUsers.length; i++) {
// bad practice to use a global aUsers
if (iUserId == aUsers[i].iUsersId) {
aUsers.splice(i, 1);
}
}
$(this).closest('tr').remove();
});
});
});

Related

dynamically created li click event not working jquery

I have unordered list defined in html file
<ul id="listbox-groups"></ul>
and i dynamically create li elements
function AddGroups(){
for (var i = 0; i < len; i++)
{
var id = groups[i].split("-")[0];
var name = groups[i].split("-")[1];
$('#listbox-groups').append('<li id="' + id + '" class="listbox-li">' + name + '</li>');
}
};
Now i am trying to catch click event on created li element.
<script type="text/javascript">
$("#listbox-groups li").on("click", function(event) {
//some code
});
</script>
I also tried
<script type="text/javascript">
$(document).on("click", "#listbox-groups li", function(event) {
//some code
});
</script>
and few other things i found here but nothing worked for me.
Anyone can help?
Just put your code inside ready function and it will work with your second attempt that using event delegation on(), check snippet bellow.
Hope this helps.
Snippet
$(function(){
var groups = ['test-1','test-2','test-3'];
var len = groups.length;
for (var i = 0; i < len; i++)
{
var id = groups[i].split("-")[0];
var name = groups[i].split("-")[1];
$('#listbox-groups').append('<li id="' + id + '" class="listbox-li">' + name + '</li>');
}
$(document).on("click", "#listbox-groups li", function(event) {
alert($(this).text()+" clicked");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="listbox-groups"></ul>
check the fiddle. seems you need to avoid default action of aHref. https://jsfiddle.net/vh08vw84/
function AddGroups(){
for (var i = 0; i < 10; i++)
{
var id = i;
var name = i;
$('#listbox-groups').append('<li id="' + id + '" class="listbox-li">' + name + '</li>');
}
};
AddGroups();
$("#listbox-groups li").on("click", function(event) {
alert($(this).attr("id"));
return false;
});

Works $(this) after $.post?

Can I use $(this).parentsUntil()... after a $.post?
I need to remember what select element from the DOM changed and then append the information collected from my PHP to next select.
//OPTION SELECTED
$('body').on('change','.provincias, .partidos', function(e) {
var idSelect = $(this).attr('id');
var dataSelect = $(this).select2('data');
var value = dataSelect.id;
$.post('php/select/script.php', {id:idSelect, id_provincia:value, id_partido:value } , function(respuesta) {
data = JSON.parse(respuesta);
if(data.control == 0){
alert(data.error)
window.location.replace(data.url);
}else{
if(idSelect == data.thisSelect){
for(var u=0; u<data.array1.length; u++){
$(this).parentsUntil('.formRow').next().children(data.nextSelect).append('<option value="' + data.array1[u].id + '">' + data.array1[u].nombre + '</option>');
}
}else if(idSelect == data.thisSelect){
for(var t=0; t<data.array1.length; t++){
$(this).parentsUntil('.formRow').next().children('".' + data.nextSelect +'."').append('<option value="' + data.array1[u].id + '">' + data.array1[u].nombre + '</option>');
}
}
}
});
});
The typical solution is to define another variable to hold the value of this, e.g. self, or in this case, you might want to call it target:
...
var target = this;
$.post('php/select/script.php', {id:idSelect, id_provincia:value, id_partido:value } , function(respuesta) {
// Use target here.
}
just save the $(this) in a variable.
$('body').on('change','.provincias, .partidos', function(e) {
var el = $(this);
...
el.parentsUntil('.formRow').next().children(data.nextSelect).append('<option value="' + data.array1[u].id + '">' + data.array1[u].nombre + '</option>');

how to build a dynamic menu using jquery?

I try to create a dynamic menu using jquery:
function createMenu(array) {
var main = $("#mainUl");
for (var i = 0; i < array.length; i++) {
main.append("<li>");
$('li').append("<a href='#" + myArray[i].id + "'><span>" + myArray[i].id + "</span></a>");
main.append("</li>");
}
}
The menu is created, but in each li i get more than one span, there is an "inside" loop (I think...)
createing more spans than needed... how can i solve/control it so each li gets
one span according to the for - loop index ?
You are seeing that behaviour because you are appending that anchor with span in selecting all the li elements.
Try,
function createMenu(array) {
var main = $("#mainUl");
for (var i = 0; i < array.length; i++) {
var xLi =("<li>").appendTo(main);
xLi.append("<a href='#" + myArray[i].id + "'><span>" + myArray[i].id + "</span></a>");
main.append(xLi);
}
}
you can do it simply as below
function createMenu(array) {
var main = $("#mainUl");
for (var i = 0; i < array.length; i++) {
main.append($("<li>").append("<a href='#" + myArray[i].id + "'><span>" + myArray[i].id + "</span></a>"));
}
}
$('li') this selector will get every li on the html so every time you iterate to create a new li element you gonna add a new span to all of them.
Try like this:
function createMenu(array) {
var main = $("#mainUl");
for (var i = 0; i < array.length; i++) {
var menuLine = $('<li>');
menuLine.html("<a href='#" + myArray[i].id + "'><span>" + myArray[i].id + " </span></a>" );
main.append(menuLine);
}
}

'tag' field jQuery

I am creating a popup menu with jQuery with some buttons. Number of buttons is flexibel. For each item in the variable 'items' there is one button. The problem: If the button is clicked I want to know to which item it belongs to.
In other programming languages there is a so called 'tag'-field where you can put an integer or an object for identification. What is the best way in jQuery?
var popup = $('<div />');
for (var i = 0; i < items.length; i++)
{
var btn = $('<div>' + items.Name + '</div>').appendTo(popup).button().click(
function(e) {
// alert($(e.target).tag);
popup.hide();
}
);
// btn.tag = i;
}
Try looking at .data(). This will allow you to store information associated with a key for any element.
var popup = $('<div />');
for (var i = 0; i < items.length; i++)
{
var btn = $('<div>' + items.Name + '</div>').appendTo(popup).button().click(
function(e) {
// alert($(e.target).tag);
popup.hide();
}
);
btn.data("index", i);
}
You can the retrieve the information using btn.data("index") where btn is a jQuery object containing the element.
Update - Accessing the element that has been clicked within a function
The this keyword will refer to the html element that has been clicked. You could alert the stored data using:
function(e){
alert($(this).data("index"));
}
You can use the "data-" attribute...
var popup = $('<div />');
for (var i = 0; i < items.length; i++)
{
var btn = $('<div ' + 'data-tag="' + i + '">' + items.Name + '</div>').appendTo(popup).button().click(
function(e) {
// alert($(e.target).tag);
alert($(this).data("tag"));
popup.hide();
}
);
// btn.tag = i;
}

Maintaining checkbox state in jQuery accordion

I have a nested accordion with a checkbox that makes an ajax call if checked, the problem is that the checkbox does not remain checked after the accordion expands.
if (childList.length > 0) {
list += '<ul class = ui-accordion>';
for (var j = 0; j < childList.length; j++) {
list += '<li><div><input type = "checkbox" class = "reqCheckBox" value="' + childList[i].ComponentID + '"/> ' + childList[j].ComponentDesc +'</div>';
var grandChildList = $.grep(data, function (n, k) {
return n.ParentID == childList[j].ComponentID;
}, false);
if (grandChildList.length > 0) {
list += '<ul class = ui-accordion>';
for (var k = 0; k < grandChildList.length; k++) {
list += '<li><div><input type = "checkbox" onclick="getReq(' + grandChildList[i].ComponentID + ')"/>' + grandChildList[k].ComponentDesc + '</div>';
var greatGrandChildList = $.grep(data, function (n, l) {
return n.ParentID == grandChildList[k].ComponentID;
}, false);
if (greatGrandChildList.length > 0) {
list += '<ul class = ui-accordion>';
for (var l = 0; l < greatGrandChildList.length; l++) {
list += '<li><div><input type = "checkbox" onclick="getReq(' + greatGrandChildList[i].ComponentID + ')"/>' + greatGrandChildList[l].ComponentDesc + '</div>';
}
list += '</li></ul>';
}
}
list += '</li></ul>';**
I know that I need to make this unobtrusive but any critiques of my JavaScript code as well would be appreciated as I am a noob. Thanks!
What you need is to persist the value of the checkbox. So when you check it your ajax calback needs to update the value of a property. This way when the accordion expands it persists the state of the checkbox.
I maintained checkbox state by adding this function
$("a").click(function (event) {
event.stopPropagation();
});
});
The following works.
$("#accordion h3 input").click(function(event) {
event.stopPropagation();
});

Categories