Getting the value of TD in a foreach loop - javascript

I have this code which show me the list of my item
<tbody class="table-color2">
<c:forEach var="defect" items="${defectList}">
<tr>
<td id="defectId"><a onclick="getDefectId()">${defect.id}</a></td>
<td>${defect.createdDate}</td>
<td>${defect.reportedBy.firstName}</td>
<td>${defect.title}</td>
<td>${defect.bugtype.description}</td>
<td>${defect.status.description}</td>
<td>${defect.priority.description}</td>
</tr>
</c:forEach>
</tbody>
what Im trying to do is to get the value of the td id="defectId" when it is clicked, my jquery script for the onclick is this :
function getDefectId(){
var defectId = $(' #defectId ').val();
alert("Defect ID " + defectId);
}
but currently, I'm getting a value of undefined, how do I get the value?

You have several issues. Firstly you're appending the same id in a loop, which will result in duplicates which is invalid. Also, a elements don't have a value to retrieve so you need to use text(). Finally note that using your current method would mean that you need to pass the this reference of the clicked element to the function.
However you can tidy all that up by using classes and hooking up the event in JS. Try this:
<tbody class="table-color2">
<c:forEach var="defect" items="${defectList}">
<tr>
<td class="defect">${defect.id}</td>
<td>${defect.createdDate}</td>
<td>${defect.reportedBy.firstName}</td>
<td>${defect.title}</td>
<td>${defect.bugtype.description}</td>
<td>${defect.status.description}</td>
<td>${defect.priority.description}</td>
</tr>
</c:forEach>
</tbody>
$(function() {
$('.defect a').click(function(e) {
e.preventDefault();
console.log($(this).text());
});
});
Working example

You can do the following(remember that id needs to be unique):
<td class="defectId"><a onclick="getDefectId(${defect.id})">${defect.id}</a></td>
And in you function:
function getDefectId(value){
alert("Defect ID " + value);
}

Try this : use text() instead of val() because you want to know the text inside td and not the value of input element.
EDIT: - Sorry, missed that there are multiple td's. In this case, you must not use same id for all tds. Just make it class and do following changes in function.
function getDefectId(){
var defectId = $('.defectId').text();
alert("Defect ID" + defectId);
}
I would suggest to use jQuery event handler instead of calling javascript function. See below code
HTML: remove onclick call
<td class="defectId">${defect.id}</td>
jQuery : register a click handler and read text
$(function(){
$('.defectId a').click(function(){
var defectId = $(this).text();
alert(defectId);
});
});

Related

How to obtain text of a <td> element from another <td> element with jquery

I am trying to use a button inside a table division to set a variable as the same value as another division in the same row, but whenever I run my code (below), it returns the value of all the table divisions concatenated together. I am unsure why this was happening, so I replaced '.children()' with 'childnodes[0]' to try and get only the first name, but this just doesn't work and I don't why.
My html looks like this:
<table>
<tr>
<td>John</td>
<td>Doe</td>
<td><button>Get First Name</button></td>
</tr>
</table>
And my Javascript is this:
$(document).ready(function(){
$("button").click(function(){
var first = $(this).closest("tr").childNodes[0].text();
alert(first)
})
});
set a variable as the same value as another division in the same row
there are lots of possibilities for this, here are some (with the most useful first (opinion based))
$("button").click(function() {
var first = $(this).closest("tr").find("td:first").text();
var first = $(this).closest("tr").find("td").first().text();
var first = $(this).closest("tr").find("td").eq(0).text();
var first = $(this).closest("tr").children().first().text();
var first = $(this).closest("tr").children().eq(0).text();
var first = $(this).closest("td").siblings().first().text();
});
it returns the value of all the table cells concatenated together
https://api.jquery.com/text
Get the combined text contents of each element in the set of matched elements, including their descendants, or set the text contents of the matched elements.
because you're passing the "tr" to text() it gets the text of all the cells (tds) and their content etc and combines them as one, so you need to limit to the first as you've attempted.
however .childNodes[0] can only be applied to a DOM element/node, while $(this).closest("tr") gives you a jquery object/collection, which doesn't have .childNodes property.
So the jquery equivalent would be to use .children().eq(0).
You could use class identifiers to get information you need as well.
<table>
<tr>
<td><span class="first-name">John</span></td>
<td><span class="last-name">Doe</span></td>
<td>
<button class="btn-get-data" data-class="first-name">Get First Name</button>
<button class="btn-get-data" data-class="last-name">Get Last Name</button>
</td>
</tr>
</table>
$(document).ready(function() {
$(".btn-get-data").click(function() {
$btn = $(this);
$tr = $btn.closest('tr');
var first = $tr.find('.' + $btn.attr('data-class')).html();
alert(first);
})
});
If you make the button click generic like so, you can add additional buttons on the page and use that to get the class within that row.
Here is a working fiddle example: https://jsfiddle.net/b1r0nucq/
you could find the :first child and get his html(), as below:
$(document).ready(function() {
$("button").click(function() {
var first = $(this).closest("tr").children(":first").html();
alert(first)
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td>John</td>
<td>Doe</td>
<td><button>Get First Name</button></td>
</tr>
</table>

Button click only works on one button out of appended list of buttons

JQUERY
i have 4 buttons that are pulled from a database and appended to a list, but only this first appended button works. All the rest wont do anything.
function getaplist(){
$.getJSON('/geticsassignments',
function(data){
console.log(data)
for (var i = 0; i < data.length; i++){
var assign = ("<tr><th><button class='btn btn-warning' id='getaptext'
value=''>"+ data[i].aparatus +"</button></th></tr>")
$('#aptbody').append(assign)
}
$('#getaptext').on('click', function(){
$("#getaptext").removeClass("btn btn-warning").addClass("btn btn-danger")
var aparatus = $(this).text()
alert(aparatus)
$.getJSON('/sendap',{
}, function(data){
console.log(data)
})
})
})
}
getaplist()
<div id='aplist'>
<table class="table">
<thead>
<tr>
<th><p style="text-align: center;">Aparatus</p></th>
</tr>
</thead>
<tbody id='aptbody'>
</tbody>
</table>
</div>
There are two problems with your code.
1- ID must be unique on the DOM.
2- You're trying to add event listeners on dynamically created elements which doesn't work the way you are trying to do.
Solution :
First Make sure the id are unique. And add event listeners with class name for example
$(document).on('click','.btn',function(){
$(this).removeClass("btn btn-warning").addClass("btn btn-danger")
var aparatus = $(this).text()
...
})
This will work for all the elements event which are added dynamically on your page
You're using the same id, getaptext, for every button. The id attribute has to be unique. You'll have to make the ids different, or use something else like a common name or class.

Get text from closest span using jQuery

I'm looking to retrieve the text inside a HTML table that is rendered via a webgrid. The text that I want is located inside a div with the class productID. My starting reference point is in the same row but the last td with the class span2. I'm trying to use jQuery's closest() method however I'm not getting any value returned.
Please see below for a section of the rendered HTML and my jQuery function:
HTML:
<tr>
<td class="span1"><div class="productID">1</div></td>
<td class="span2">Listing</td>
<td class="span2">Full Districtution</td>
<td class="span2">$1,350.00</td>
<td class="span2">2016-01-01</td>
<td class="span2"><div title="This is my brand new title!" data-original-title="" class="priceToolTip">2016-04-30</div></td>
<td>Select</td>
</tr>
jQuery:
$(".priceToolTip").mouseover(function () {
var row = $(this).closest("span1").find(".productID").parent().find(".productID").text();
console.log("Closest row is: " + row);
});
The .closest() method looks for a match in the ancestors. So you can use it to grab the tr then look for .productID like so:
var productID = $(this).closest('tr').find('.productID').text();
Or:
var productID = $(this).parent().find('.productID').text();
Or:
var productID = $(this).siblings('.span1').find('.productID').text();
.span1 is not the closest element of .priceToolTip. Use closest("tr").find(".span1 .productID") like following.
$(".priceToolTip").mouseover(function () {
var row = $(this).closest("tr").find(".span1 .productID").text();
console.log("Closest row is: " + row);
});

Get particular instance of a class with a Div

How can I use jQuery to get a particular instance of a class(headerGrid) within a Div(products).
I need to be able to get an instance of the class 'headerGrid' classed span which says "Get this Text". The instance is represented as the value within swap2(). My code is as follows...
<table id="products">
...
<tr>
<td>
<a onclick="swap2(1);"><img src="images/products/thumbs/image.png"/></a>
</td>
<td valign="top" class="product-text">
<span class="headerGrid">Get this Text</span><br /><br />
text
</td>
</tr>
...
</table>
E.g. if onclick="swap2(5);" then I need to get the 5th instance of '.headerGrid'
EDIT
Further more I need to select the text("Get this Text") rather then the object itself. Other wise it returns object [object Object].
I also tried selecting with .innerHTML which returns undefined.
Use the eq() selector. Example:
$("#products span.headerGrid").eq(4) //Zero based index
With your function:
function swap2(n) {
//Zero based index, subtract 1
var theText = $("#products span.headerGrid").eq(n - 1).html();
...
}
Using the :nth-child selector:
$('#products span.headerGrid:nth-child(5)')
Use $("#products span.headerGrid:nth-child(5)"), which will return the 5th span with class headerGrid in your element with ID products.
Function swap could look like this:
function swap(n){
var element = $("#products span.headerGrid:nth-child(" + n + ")");
//Rest of code
}
Small notice: You've mentioned DIV(products) in your question, but your code shows table.

jQuery remove elements after creation

I'm building a jQuery sortable list where the user can add items from a table, drag and sort and/or remove them. I can add and sort no problem, but I can't work out how to remove an item element after it has been added. I'm relatively new to js / jQuery, so I have a feeling there's something new to learn here about how it works!
I'll leave out the ui.sortable stuff here as I'm only concerned with removing items..
<table>
<tr>
<td><a class="addrelease" href="#" cat_id="1">add</a></td>
<td>Item 1</td>
</tr>
<tr>
<td><a class="addrelease" href="#" cat_id="2">add</a></td>
<td>Item 2</td>
</tr>
</table>
<div id="list"></div>
<script>
$("a.addrelease").click(function (e) {
e.preventDefault();
cat_id = $(this).attr('cat_id');
remove_str = " remove";
str = cat_id + remove_str;
$(str).appendTo("#list").hide().fadeIn();
});
$("a.remove").click(function (e) {
alert("This function doesn't seem to be called");
$(this).parent().remove(); //Doesn't happen..
});
</script>
I'm guessing that javascript doesn't recognize the new generated items - but I'm not sure, so I'm not sure where to start fixing it
Cheers
You should use live function to attach events to dynamically added elements.
Try this to bind click event to a.remove elements:
$("a.remove").live("click", function (e) {
alert("This function doesn't seem to be called");
$(this).parent().remove(); //Doesn't happen..
});
You're absolutely right, javascript won't recognise new items.
jQuery selectors will normally only match against elements currently in the document. When you use $("a.remove").function(), jQuery builds a list of nodes matching "a.remove", then calls function() on each of them.
The .live() function is special, and doesn't attach events directly to elements - instead, events bubbling up to the top of the DOM are evaluated to see if they match the selector.
IMHO, the best approach is to bind the remove handler when you create the new list entry:
str = cat_id + remove_str;
var remove = $(str);
remove.appendTo("#list").hide().fadeIn();
remove.click(function(e) { .... })
Disclaimer: Typed late at night & not tested!
Here is my answer of how I think you should modify your code:
http://jsfiddle.net/RY5CP/
<table>
<tr>
<td><a class="addrelease" href="#" rel="1">add</a></td>
<td>Item 1</td>
</tr>
<tr>
<td><a class="addrelease" href="#" rel="2">add</a></td>
<td>Item 2</td>
</tr>
</table>
<div id="list"></div>
<script type="text/javascript">
$("a.addrelease").click(function(e) {
e.preventDefault();
var catId = $(this).attr('rel');
var itemName = $(this).closest('td').next('td').text();
var newItem = '<p>' + catId + ' ' + itemName + ' remove';
$(newItem).appendTo('#list').hide().fadeIn();
});
$("a.remove").live('click', function(e) {
$(this).parent('p').remove();
});
</script>
It's not valid to use cat_1, cat_2 as HTML attributes. You can use the rel attribute if you need to have a specific value to be associated to your items
Use the live() method to have the click event handler automatically attached to items dynamically created

Categories