Passing id into function from onclick method - javascript

I know there are many of these types of questions already on here, but I can't find one that matches my specific case.
I just want to pass an id variable into a function from an onclick event, but there's something not right about the way I've got is set up
The goal is to be able to remove the rows that have been added when the X is clicked
$(document).ready(function () {
$("#subjectlist")
.change(function () {
console.log("hit");
$("select option:selected").each(function () {
console.log($("select option:selected"));
var id = 1;
$('#overview').append("<tr id='id'><td>" +
$(this).text() + "</td><td id='id'
onclick='removeItem(id)'>" + "X" + "</td></tr>");
id = id + 1;
});
})
.trigger("change");
$(".btn1").click(function () {
$("#subjectlist").toggle();
});
});
function removeItem(id) {
console.log(id.val);
console.log(id);
$('#overview').find('tr td').eq(id).remove();
}

If your goal is to remove the 'td' element that is clicked. Try this...
$(document).ready(function () {
var id = 1;
$("#subjectlist")
.change(function () {
console.log("hit");
$("select option:selected").each(function () {
console.log($("select option:selected"));
//var id = 1; moved this initialization up a scope level
//on the line below I corrected the concatenation to have unique id's, and removed inline click event.
$('#overview').append("<tr id='id'><td>" + $(this).text() + "</td><td id="+id+">" + "X" + "</td></tr>");
id = id + 1;
});
})
.trigger("change");
$(".btn1").click(function () {
$("#subjectlist").toggle();
});
// added click event to your dynamic element
$("#overview").on('click','td', function() {
$(this).parent().remove();
});
});
/* removed
function removeItem(id) {
console.log(id.val);
console.log(id);
$('#overview').find('tr td').eq(id).remove();
}*/

Your appending string is incorrectly formatted.
Drop the id attribute on the table column since your removeItem() function should be targeting the table row.
You can use back ticks to generate template literals like so...
$('#overview').append(`<tr id="${id}">
<td>${$(this).text()}</td>
<td onclick="removeItem(${id});"> X </td>
</tr>`);
The jQuery.eq() function is an index based filter, not an selector filter. You can then utilise the id selector...
function removeItem (id) {
$(`#${id}`).remove();
}

Try changing this
$('#overview').append("<tr id='id'><td>" + $(this).text() + "</td><td id='id' onclick='removeItem(id)'>" + "X" + "</td></tr>");
To this... should be less confusing, regarding the quote-nesting... notice the use of backticks (`) on the outermost quote level. Also restyled it to make it easier to read, and match html syntax more visually.
$('#overview').append(
`<tr id=x_id_`+id+`>` +
`<td>` +
$(this).html() +
`</td>` +
`<td onclick="$('#x_id_` +
id +
`').remove()">` +
`X` +
`</td>` +
`</tr>`
);
You can ditch the removeItem function entirely.
Since I don't have the rest of your code, not totally sure about the change to the $().html vs $().text, but this should produce a clickable element that will remove the whole row with that id label, which is coded into the rows id and the onclick function.
This will produce html like:
<tr id=x_ix_1><td>PREVIOUS STUFF HERE</td><td onclick='removeItem(`x_id_1`)'>X</td></tr>
Couple things:
First, keep in mind you can only have one element with a particular id at a time. Duplicates will cause errors (but you can remove an element with a particular id and make a new one with that same id, they just can't co-exist).
If you don't want the row removed, but just the td, move the bit about the elements id from the tr to the td-- can't have same id on both.
The quote-nesting was incorrect with the id variable, so was adding it as litteral text (just the string 'id', not the variable content)...
And html id's need to start with a letter. So I re-nested it so the id will parse as variable contents, and the html output will contain 'x_id_' prepended to the variable content... i.e. x_id_0 x_id_1 etc.

Related

How to remove div elements from the DOM tree one by one?

Here is my example.
By clicking the add button, I add a user card. "Clear button" removes all cards. How to remove cards one by one clicking on the "close" icon in each card?
HTML file
<div class="header">
<button id="clear" class="button clear">Clear</button>
<button id="button" class="button add">Add user</button>
</div>
<div id="content">
</div>
JS file
var root = 'https://jsonplaceholder.typicode.com';
var index = 0;
$.ajax({
url: root + '/posts/1/comments',
method: 'GET'
}).then(function(data) {
$("#button").click(function() {
var notificationMessage = "Oops, there are no more user cards to display";
if (index >= data.length ) {
return alert(notificationMessage);
}
$("#content").append('<div id="card"><div class="title"><div class="image"></div><div id="name">'
+ data[index].name + '</div><span id="close"></span></div><div id="description">'
+ data[index].body + '<a href="mailto:" id="email">'
+ data[index].email + '</a></div></div>'
);
index++;
// remove all cards from a list and return index equally [0], to be able add user card again.
$("#clear").click(function() {
$("#card").remove();
index = 0;
});
});
});
//How to remove card by clicking on the close button?
have you try to use class in card element?
because id selector only get first matching element
$.ajax({
url: root + '/posts/1/comments',
method: 'GET'
}).then(function(data) {
$("#button").click(
function() {
var notificationMassage = "Oops, there are no more user cards to display";
if (index >= data.length ) {
return alert(notificationMassage);
}
$("#content").append('<div class="card"><div class="title"><div class="image"></div><div class="name">'
+ data[index].name + '</div><span class="close"></span></div><div class="description">'
+ data[index].body + '<a href="mailto:" id="email">'
+ data[index].email + '</a></div></div>'
);
index++;
// remove all cards from a list and return index equally [0], to be able add user card again.
$("#clear").click(function() {
$("#content").html('');
index = 0;
});
});
to remove one by one add this code
// remove one cards from a list.
$("#content").on("click", ".close", function() {
$(this).closest('div.card').remove();
});
First of all you need to change id to to class.
And here is solution:
codepen.io/ivanchuda/pen/xRjyJp
First of all, ids should be unique. I recommend changing yours into classes.
$("#content").append('<div class="card"><div class="title"><div class="image"></div><div class="name">'
+ data[index].name + '</div><span class="close"></span></div><div id="description">'
+ data[index].body + '<a href="mailto:" id="email">'
+ data[index].email + '</a></div></div>'
);
Now that we have all close icons with class close, we can add the following listener for all .close buttons to remove only the card which contains them.
$(document).on('click', '.close', function(){
$(this).closest('.card').remove(); // remove only closest '.card'
});
First off, I would change the ID on the divs to class instead since you are generating multiple cards. IDs should be unique. Then I would change the code to add one more line to your close-span:
<span class="close" onclick="$(this).parent().parent().remove()"></span>
Try like this
See the updated codeopen
Change the id to class .And match with parent() of parent()
on() more important
$(document).on("click",".close",function() {
$(this).parent().parent().remove()
});
You can use this code to implement what you want:
$("body").on("click", ".close", function(e) {
$(this).closest('.card').remove();
});
Note: Remember that use only single ID on a single page, instead use classes to make it work
See this CodePen
// jQuery on() method description
.on( events [, selector ] [, data ], handler )
See more about jQuery's on() method.
Hope this helps!
The short and not elegant answer is:
$("#content").on("click", "span[id=close]", function() {
$(this).closest("div[id=card]").remove();
});
This should work, but you need to do a better job than this. Your HTML is invalid, since id is expected to be unique and you use the very same id for different items. You could use classes instead, or make sure that the identifier is unique. Note that your SEO will instantly improve if you make your HTML valid. If you use classes instead of not-unique ids, then the script above will change to this one:
//content is unique, therefore it can remain an id
$("#content").on("click", "span.close", function() {
$(this).closest("div.card").remove();
});

How to dynamically remove records from a table via Jquery

I have an html table that is dynamically created.
The following jQuery code captures the tr that the user has selected in that table, and populates another table called "selected_users" with specific data from the row that's been picked.
$('#available_users tbody').on('click', 'tr', function () {
var id = this.id;
var tr;
tr=$('<tr/>');
var index = $.inArray(id, selected);
if ( index === -1 ) {
selected.push( id );
var tds = $(this).find('td');
tr.append("<td>" + tds.eq(1).text() + "</td>");
tr.append("<td>" + tds.eq(3).text() + "</td>");
$('#selected_users').append(tr);
} else {
selected.splice( index, 1 );
}
$(this).toggleClass('selected');
} );
Question
This logic is working. But now what I need to do is when users deselect a previously selected record from the available_users table, I need to remove it from the "selected_users" table.
What I've tried So far:
The first thing I tried to do is to assign an ID to the <TR> that I create in the "selected_users" table, so that I can use this id to find the row I want to delete.
I tried to change my code to look like this:
var index = $.inArray(id, selected);
if ( index === -1 ) {
selected.push( id );
var tds = $(this).find('td');
tr.append("<td>" + tds.eq(1).text() + "</td>");
tr.append("<td>" + tds.eq(3).text() + "</td>");
tr.attr('id') = id.substring(4); //******* NEW ********
$('#selected_users').append(tr);
But it bombs with an error "ReferenceError: invalid assignment left-hand side".
The other question is how to remove the from the selected_users table. I'd like to put the logic in the else path ...
} else {
selected.splice( index, 1 );
//*** add logic to remove also from the selected_users table.
}
Thanks.
EDIT 1
All the code I've posted here works, except the attempt to dynamically assign the ID attribute to the new <TR> I'm adding. I think in this case, all the details might be making things more complicated ???
Maybe it would simplify things if I just asked how do so something like this:
var tr;
tr.append("<td>value1</td>");
$('#test_table').append(tr);
When doing something like the above, how would you assign an id of "id=123" to the <tr>?
Also, if you only had the row id (<tr id=123>), how could you delete the entire row from test_table?
First, I'm assuming that this is the line that "bombs with an error ReferenceError: invalid assignment left-hand side":
tr.attr('id') = id.substring(4);
I make this assumption because attr('id') will return a String, which is immutable, and you're trying to assign a new String (of id.substring(4)) to that existing string.
If you wish to set a new value to the id you need to use the setter form of the attr() method:
tr.attr('id', id.substring(4))`
Or, assuming the substring is to be taken from the current id:
tr.attr('id', function (index, currentProperyValue) {
return currentPropertyValue.substring(4);
});
In the above the argument-names are user-defined, the first argument (above: 'index') is the index of the current element returned by the collection in the tr variable; the second (above: 'currentPropertyValue') represents the current-value of the property we're changing with the method.
…if you only had the row id (<tr id=123>), how could you delete the entire row from test_table?
Simply, using jQuery:
$('#123').remove();
Which will remove the element from the document (wherever that element appears within the document, bearing in mind that duplicate ids are invalid, so if two elements occur with that same id only the first element with that id will be removed).
Alternatively, but still simply, using plain JavaScript; here we're using a variable because we need to get the same element twice:
var elem = document.getElementById('123');
elem.parentNode.removeChild(elem);
References:
JavaScript:
document.getElementById().
Node.parentNode.
Node.removeChild().
String.
String.prototype.substring().
jQuery:
attr().
remove().

add and remove elements from form, 1st click works, subsequent clicks dont

I am trying to add/remove an element to a form based on a checkbox in a previous part of the form. My problem is, the first time a user clicks on anything in checkContact, the form is appended correctly. If the user unchecks the box, it is removed correctly. When the user re-clicks the checkbox, the element is not added..
$('.checkContact').click(function(){
var addInfo = "<div class='middleRow'><input type='text' id='"+val+"_name[]' name='"+val+"'_name[]'></div>";
if($(this).is(':checked'))
{
alert(addInfo);
$('#'+divId).append(addInfo);
}
else
{
$('#'+divId).detach();
// i have also tried .remove();
}
fiddle:
Fiddle
In the else part, you are removing the element $('#' + divId) from the dom tree instead of removing its content. You have to only empty the container element because in the if block you are adding the target markup to the container element.
$('.checkContact').click(function () {
var val = $(this).val();
var divId = val + '_div';
var addInfo = "<div class='middleRow'><input type='text' id='" + val + "_name[]' name='" + val + "'_name[]'></div>";
if (this.checked) {
//alert(addInfo);
$('#' + divId).html(addInfo);
} else {
//you are removing the container instead of removing its content
$('#' + divId).empty();
}
});
Demo: Fiddle
When you uncheck the box, you remove name_div from the DOM with .detach. So when you click the box again, the selector doesn't find anything, so there's nothing to append to.
Change .detach() to .empty()
DEMO
But perhaps a better method would be to hide and show the DIV, rather than add and remove the content.
In your code you have used detach() or empty(), it would remove the element from the DOM and after that you will not be able to insert html by using .html() method. Instead of using detach() or remove() you have to use .empty() or .html(''), this will keep the element in DOM, so you can again and again append the element.
$('.checkContact').click(function(){
var addInfo = "<div class='middleRow'><input type='text' id='"+val+"_name[]' name='"+val+"'_name[]'></div>";
if($(this).is(':checked'))
{
alert(addInfo);
$('#'+divId).append(addInfo);
}
else
{
$('#'+divId).html('');
//or $('#'+divId).empty();
}
});
see here:
http://jsfiddle.net/WYmVU/

Inject JavaScript variable as value in anonymous function

I have a form where I add inputs dynamically. When I add a new input I increment a global id variable and concatenate it to the input's id so it will be unique. I also create a delete button for each input that should remove that input and himself (through removing the container <div> they are in). I do the remove process by adding an anonymous function to the delete button's click event via JQuery:
$('#deletebutton' + id).click(function(){
$('#inputcontainer' + id).remove();
});
The only problem with this solution that it isn't work in the way I excepted it. When I click any of the delete buttons it will delete the last input container because when I click, it executes the anonymous function and evaluate the id variable at that time, so the selected id will be the last input's id. So always the last input container will be deleted.
Is there a way to rewrite this function so when I add it to the click event, than it will evaluate the id, inject it and handle the selection as if it had been written like #inputcontainer1, #inputcontainer2, etc.
I can make this by adding the function's body to the button's onclick() event:
var newbutton = '<button id="deletebutton' + id + '" type="button" onclick="javascript:$(\'#inputcontainer' + id + '\').remove();">x</button>';
But is there a way doing this with the JQuery click() way?
To answer the specific question, you'd have to dig the id out of the DOM:
$('#deletebutton' + id).click(function(){
var id = $(this).attr("id").replace('deletebutton','');
$('#inputcontainer' + id).remove();
});
You could also store it as data when you create the delete button:
<button data-id="1" id="deletebutton1">
$('#deletebutton' + id).click(function(){
var id = $(this).data("id");
$('#inputcontainer' + id).remove();
});
Note that in both of these cases, id is a string, not an integer.
When I click any of the delete buttons it will delete the last input container [...]
If your 1st snippet is inside a loop, id probably isn't being scoped to each iteration. So, by the time one of the click() events is triggered and it's trying to use .remove(), id will have already been set to the last value given while looping.
You can use an IIFE to create an additional function scope for keeping a different id for each iteration (ref: closure).
/* loop */ {
var id = ...;
(function (id) {
$('#deletebutton' + id).click(function(){
$('#inputcontainer' + id).remove();
});
})(id);
}
Though, for future reference, ECMAScript 6 is adding block scoping which should allow for:
/* loop */ {
let id = ...;
$('#deletebutton' + id).click(function(){
$('#inputcontainer' + id).remove();
});
}
$('#deletebutton' + id).click(function(){
$(this).parent().remove();
});
If the container isn't a direct parent and doesn't have a class you could do:
$('#deletebutton' + id).click(function(){
var idNum = $(this).attr("id").replace('deletebutton','');
$("#inputcontainer"+idNum).remove();
});
If you've got appropriate classes (or can add them), this would be best:
$(document).on("click",".deleteButton",function() {
$(this).parents(".inputContainer").remove();
});

Dynamically assign id to div and use that to call jquery slide effects

I am reading contents from JSON file and adding to div with unique IDs. I need to call jquery slide down effects to each div. Lets us consider the case, on clicking (div id=A1) it should slide down and show (div id=B1), in that way I have div with IDs A(1..N) and B(1..N).
var i=1;
$.each(items, function (index, item) {
$(document).ready(function(){
$("#A"+i).click(function(){
$("#B"+i).slideToggle();
});
});
$("#allContents").append('<div id="A'+i+'">' + item.Name + '</div>');
$("#allContents").append('<div id="B'+i+'">' + item.Details + '</div>');
i++;
});
This is the closest code I could derive to, but it is not working. If anyone could help me fix or suggest a better way to get this thing working it would be great. Thanks a lot!
$('#allContents').on('click', 'div[id^=A]', function() {
$('div#B' + this.id.replace('A','')).slideToggle();
});
A little explain
div[id^=A] point out those div whose id start with A.
this.id retrieve the id of clicked element.
this.id.replace('A','') replace A form the id and get the numeric index which equal to index of B.
$('div#B' + this.id.replace('A','')) point to element id=B1, id=B2 and so on.
Full code
// you can bind event handler outside ot loop
$('#allContents').on('click', 'div[id^=A]', function() {
$('div#B' + this.id.replace('A','')).slideToggle();
});
$.each(items, function(index, item) {
$("#allContents").append('<div id="A' + i + '">' + item.name + '</div>');
$("#allContents").append('<div id="B' + i + '">' + item.Details + '</div>');
i++;
});
Working Sample
Note
As you're creating div from A(1..N) and B(1..N) dynamically so you need delegate event handler (aka live event).
Syntax of jQuery .on() for delegate event is like following:
$(container).on(eventName, target, handlerFunction)

Categories