Javascript Checkbox From a Table Returning Undefined - javascript

When I run the following code the alert comes back as 'undefined' when I would like is to return True or False depending on if the checkbox is check at the time that the user triggers the JavaScript to run.
The user is triggering it with a button. Currently when the user presses the button the script returns a 'undefined' for each row of the table.
Eventually I would like to create a JavaScript array that I will pass back to the server with an Ajax call but this is of little use if I can cannot determine the state of the check boxes for every row of the table.
Also, I'm using Jinja2 templating which explains the curly brackets but this should be of little consequence because the table is being created without issue when the HTML renders.
var table = document.getElementById("filterTable");
for (var i=1; i<table.rows.length; i++){
var isChecked = (table.rows[i].cells[2].checked);
alert(isChecked);
My table looks like this:
<table class="table table-condensed table hover" id = "filterTable">
<thead>
<tr>
<th>Origin</th>
<th>Destination</th>
<th>Active</th>
</tr>
</thead>
<tbody>
{% for dep in dependencies %}
<tr class="row">
<td><p>{{dep.origin}}</p></td>
<td><p>{{dep.destination}}</p></td>
<td>
<input type="checkbox" value="isSelected"/>
</td>
</tr>
{% endfor %}
</tbody>
</table>

The checkbox is the first child of td not the td itself (cells[2] returns third td) so checked property of td element would be always undefined.
You can get the checkbox from children property.
var isChecked = table.rows[i].cells[2].children[0].checked;
var table = document.getElementById("filterTable");
for (var i = 1; i < table.rows.length; i++) {
var isChecked = (table.rows[i].cells[2].children[0].checked);
alert(isChecked);
}
<table id="filterTable">
<thead>
<tr>
<th>Origin</th>
<th>Destination</th>
<th>Active</th>
</tr>
</thead>
<tbody>
<tr class="row">
<td>
<p>{{dep.origin}}</p>
</td>
<td>
<p>{{dep.destination}}</p>
</td>
<td>
<input type="checkbox" value="isSelected" />
</td>
</tr>
</tbody>
</table>
In case there are other elements as the child then you can get it using querySelector() method with attribute equals selector.
var isChecked = table.rows[i].cells[2].querySelector('[type="checkbox"]').checked;
var table = document.getElementById("filterTable");
for (var i = 1; i < table.rows.length; i++) {
var isChecked = (table.rows[i].cells[2].querySelector('[type="checkbox"]').checked);
alert(isChecked);
}
<table id="filterTable">
<thead>
<tr>
<th>Origin</th>
<th>Destination</th>
<th>Active</th>
</tr>
</thead>
<tbody>
<tr class="row">
<td>
<p>{{dep.origin}}</p>
</td>
<td>
<p>{{dep.destination}}</p>
</td>
<td>
<input type="checkbox" value="isSelected" />
</td>
</tr>
</tbody>
</table>

table.rows[i].cells[2] only find the td that contains the checkbox.
You need to query for the checkbox before you check the property.
var td = table.rows[i].cells[2];
var checkbox = td..querySelector('input[type="checkbox"]');
var isChecked = checkbox.checked;

Related

Create array of non hidden td rows

So I have a table where the users can filter out specific rows, by checking a checkbox. If a checkbox is selected then, some rows will get the hidden state.
I want to create a array with all the rows that isn't hidden, but I can't seem to get the state of the <td>.
The tables id is ftp_table and the rows I need the data from has the class name download. I tried to so something like this, to get the visibility value, but without any luck. The function is triggered after a hide row function has run.
function download_log() {
var rows = document.getElementsByClassName("download");
var log = [];
for (var i = 0; i < rows.length; i++) {
// Check if item is hidden or not (create a if and push into array)
console.log(getComputedStyle(rows[i]).visibility);
// append new value to the array IF NOT HIDDEN
log.push(rows.item(i).innerHTML);
}
}
The output I get when i hide something is everything is visible?:
Here is a example of the table, where all info rows has been hidden:
<table class="ftp_table" id="ftp_table">
<tbody>
<tr class="grey">
<th>Log</th>
</tr>
<tr class="info" hidden>
<td class="download">2021-10-06 12:38:15.946 INFO [conftest:101] -------------- Global Fixture Setup Started --------------</td>
</tr>
<tr class="debug">
<td class="download">2021-10-06 12:38:16.009 DEBUG [Geni:37] Initializing</td>
</tr>
<tr class="info" hidden>
<td class="download">2021-10-06 12:38:16.059 INFO [Wrapper:21] Downloading</td>
</tr>
<tr class="info grey" hidden>
<td class="download">2021-10-06 12:38:16.061 INFO [Handler:55] AV+</td>
</tr>
<tr class="debug grey">
<td class="download">2021-10-06 12:38:16.063 DEBUG [Session:84] GET'</td>
</tr>
</tbody>
</table>
You could use the following selector :
document.querySelectorAll("#ftp_table tr:not([hidden]) td.download");
It will select the td.download elements in tr that are not hidden in your table.
var visibleTds = document.querySelectorAll("#ftp_table tr:not([hidden]) td.download");
var arr = [];
for(let i = 0; i < visibleTds.length; i++){
arr.push(visibleTds[i].innerText);
}
console.log(arr);
<table class="ftp_table" id="ftp_table">
<tbody>
<tr class="grey">
<th>Log</th>
</tr>
<tr class="info" hidden>
<td class="download">2021-10-06 12:38:15.946 INFO [conftest:101] -------------- Global Fixture Setup Started --------------</td>
</tr>
<tr class="debug">
<td class="download">2021-10-06 12:38:16.009 DEBUG [Geni:37] Initializing</td>
</tr>
<tr class="info" hidden>
<td class="download">2021-10-06 12:38:16.059 INFO [Wrapper:21] Downloading</td>
</tr>
<tr class="info grey" hidden>
<td class="download">2021-10-06 12:38:16.061 INFO [Handler:55] AV+</td>
</tr>
<tr class="debug grey">
<td class="download">2021-10-06 12:38:16.063 DEBUG [Session:84] GET'</td>
</tr>
</tbody>
</table>
Why don't you use classList instead of style props ?
Like :
rows[i].classList.contains("hidden")

Get column value onClick in nested HTML Table [Javascript]

I have a nested HTML table which expands on click. When I click inner row, I would like to get column value. Right now, I am getting the column value on click of outer row.
For instance in the below image, when I click coding/testing, I would like to pass an alert as "Place". Right now, I get alert as "place" when I click city.
Component:
trigger(){
var table: any = document.getElementById("table");
var rows = table.rows;
for (var i = 0; i < rows.length; i++) {
rows[i].onclick = (function (e) {
var j = 0;
var td = e.target;
while( (td = td.previousElementSibling) != null )
j++;
alert(rows[0].cells[j].innerHTML);
});
}
}
Demo
I'm not sure why you have this code in your trigger function. But, if you need to get the column name when a data cell is clicked, you can use the following approach.
Inject into your trigger function call a current event object and your header row element template variable:
<table class="table table-hover table-bordered table-responsive-xl" id="table">
<tr #header>
</tr>
<tbody>
<ng-container *ngFor="let data of data1">
<ng-container *ngIf="data.expanded">
<tr *ngFor="let data of findDetails(data)" (click)="trigger($event, header)">
</tr>
</ng-container>
</ng-container>
</tbody>
</table>
So, #header name is assigned to the first tr element and then it's passed along with $event to the trigger function.
In your trigger function, consume these two parameters. $event will be a regular MouseEvent object and header will be a regular tr element. After this, you can find the clicked column header by the clicked cell index in your row. gsnedders in the StackOverflow thread provided a solution for how to find the element index inside its parent. Your trigger function may look like:
trigger($event, header) {
const index = this.getChildNumber($event.target);
alert(header.childNodes[index].textContent.trim());
}
This StackBlitz project illustrates this approach.
You don't need any DOM manipulation, you can simplify your solution as below:
app.component.ts
// .......
export class AppComponent {
trigger(columnName: string) {
alert(columnName);
}
// .......
}
app.component.html
<table class="table table-hover table-bordered table-responsive-xl" id="table">
<tr>
<td> Name </td>
<td> Place </td>
<td> Phone </td>
</tr>
<tbody>
<ng-container *ngFor="let data of data1">
<tr (click)="data.expanded = !data.expanded">
<td (click)="trigger('Name outer')"> {{ data.expanded ? '–' : '+'}} {{data.name}} </td>
<td (click)="trigger('Place outer')"> {{data.place}} </td>
<td (click)="trigger('Phone outer')"> {{data.phone}} </td>
<td (click)="trigger('Hobbies Outer')"> {{data.hobbies}} </td>
<td (click)="trigger('Profession outer')"> {{data.profession}} </td>
</tr>
<ng-container *ngIf="data.expanded">
<tr *ngFor="let data of findDetails(data)">
<td style="padding-left: 12px" (click)="trigger('Name inner')"> {{data.datades.name}} </td>
<td (click)="trigger('Hobbies inner')"> {{data.datades.hobbies}} </td>
<td (click)="trigger('Profession inner')"> {{data.datades.profession}} </td>
</tr>
</ng-container>
</ng-container>
</tbody>
</table>

How to get multiple selected cell array values with checkbox in jquery, then send with ajax post

How should I get an array value from a table cell when clicking checkbox with jQuery? If I've selected cell 1, I want to get array like ["BlackBerry Bold", "2/5", "UK"], but if I've selected all of them, I want to get all the data in the form of an array of arrays.
<table border="1">
<tr>
<th><input type="checkbox" /></th>
<th>Cell phone</th>
<th>Rating</th>
<th>Location</th>
</tr>
<tr>
<td align="center"><input type="checkbox"/></td>
<td>BlackBerry Bold 9650</td>
<td>2/5</td>
<td>UK</td>
</tr>
<tr>
<td align="center"><input type="checkbox" /></td>
<td>Samsung Galaxy</td>
<td>3.5/5</td>
<td>US</td>
</tr>
<tr>
<td align="center"><input type="checkbox"/></td>
<td>Droid X</td>
<td>4.5/5</td>
<td>REB</td>
</tr>
Please help.
Onclick get 3 children of the parent and add content to data. Used jquery nextAll for siblings and splice the 3 required.
Attached event to the table, onclick will check if element is INPUT.
If it's input, will get parent of that input which will be <td>.
For this parent element, will get three siblings using jquery.
Will add in selected if not present else delete, using indexOf.
CodePen for you to playaround: [ https://codepen.io/vivekamin/pen/oQMeXV ]
let selectedData = []
let para = document.getElementById("selectedData");
let tableElem = document.getElementById("table");
tableElem.addEventListener("click", function(e) {
if(e.target.tagName === 'INPUT' ){
let parent = e.target.parentNode;
let data = [];
$(parent).nextAll().map(function(index, node){
data.push(node.textContent);
})
let index = selectedData.indexOf(JSON.stringify(data))
if(index == -1){
selectedData.push(JSON.stringify(data));
}
else{
selectedData.splice(index,1);
}
para.textContent = "";
para.innerHTML = selectedData ;
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table border="1" id="table">
<tr>
<th><input type="checkbox" /></th>
<th>Cell phone</th>
<th>Rating</th>
<th>Location</th>
</tr>
<tr>
<td align="center"><input type="checkbox"/></td>
<td>BlackBerry Bold 9650</td>
<td>2/5</td>
<td>UK</td>
</tr>
<tr>
<td align="center"><input type="checkbox" /></td>
<td>Samsung Galaxy</td>
<td>3.5/5</td>
<td>US</td>
</tr>
<tr>
<td align="center"><input type="checkbox"/></td>
<td>Droid X</td>
<td>4.5/5</td>
<td>REB</td>
</tr>
</table>
<h3> Selected Data: </h3>
<p id="selectedData"></p>
Updated to meet your needs.
create a function to build the array values based on looking for any checked inputs then going to their parents and grabbing the sibling text values
attach your change event to the checkbox click even.
I provided a fiddle below that will output the array in the console.
function buildTheArray(){
var thearray = [];
$("input:checked").parent().siblings().each(function(){
thearray.push($(this).text());
});
return thearray;
}
$("input[type='checkbox']").change(function(){
console.log(buildTheArray());
});
Fiddle:
http://jsfiddle.net/gcu4L5p6/

creating table within table by pressing button

I currently have a table and in one of the <td>, I have input type of checkbox. where if user clicks on it, it will create different table.
<div style="padding-left:170px;">
<table width="80%" border="1" padding-left:50px>
<tr>
<td>
<table border="1" style="float:left">
<th>Portal01</th>
<tr>
<td style= "padding:12px;" align="left" >
<input type="test0" id = "test0" name="liveDiff" onchange = "expandService()"> blah_0
</td>
<td>
blah_1
</td>
<td>
blah_2
</td>
</tr>
</table>
</td>
</tr>
</table>
I have it set up where if user clicks on checkbox next to blah_0, it should create different table within this table. I am not sure if this is possible with JavaScript and if not, what would be alternate way to approach this situation.
it is possible.
function expandService(){
document.getElementById('the_id_of_the_td_that_will_contain_the_new_table').innerHTML =
'<table><tr>...</tr></table>';
}
Another way is to use appendChild(), here is an example:
function expandService(chkId, tblId, totalRows, totalCols){
var tbl = document.createElement('table');
tbl.id = tblId;
var row, col, spn;
for(var i=0; i<totalRows; i++){
row = document.createElement('tr');
for(var j=0; j<totalCols; j++){
col = document.createElement('td');
spn = document.createElement('span');
spn.innerHTML = 'your-text';
col.appendChild(spn);
row.appendChild(col);
}
tbl.appendChild(row);
}
var chk = document.getElementById(chkId);
// td is the parent of checkbox
chk.parentNode.appendChild(tbl);
}
Sample usage:
<input type="checkbox" id="test0" name="liveDiff" onchange="expandService(this.id, 'your-table-id', 5, 4)">
It creates a table with 5 rows and 4 columns.
This is possible with javascript. One potential way to go is to use innerHTML. Use jQuery or just document.getElementByID to select the element that corresponds to your cell and insert a table inside of it. Here is an example fiddle using your code as a base.
<div style="padding-left:170px;">
<table width="80%" border="1" padding-left:50px>
<tr>
<td>
<table border="1" style="float:left">
<th>Portal01</th>
<tr>
<td id="foo" style= "padding:12px;" align="left" >
<input type="test0" id = "test0" name="liveDiff"> blah_0
</td>
<td>
blah_1
</td>
<td>
blah_2
</td>
</tr>
</table>
</td>
</tr>
</table> ​
js:
var makeTable = function(contents){
return '<table><td>' + contents + '</td></table>'
}
document.getElementById("test0").onchange = function(){
document.getElementById("foo").innerHTML = makeTable("foo")
}
​

Change background-color of 1st row in the table

Below is my table that is getting populated with spry dataset
Here is my dataset
var ds1 = new Spry.Data.XMLDataSet("/xml/data.xml", "rows/row");
Here is my jquery inside a method that is called on a button click
function addRow()
{
var newRow = new Array();
var nextID = ds1.getRowCount();
newRow['ds_RowID'] = nextID;
newRow['id'] = "x";
newRow['name'] = "Abhishek";
newRow['country'] = "India";
ds1.dataHash[newRow['ds_RowID']] = newRow;
ds1.data.push(newRow);
Spry.Data.updateRegion(ds1);
ds1.sort('name','descending');
ds1.setCurrentRow(newRow.ds_RowID);
$(".trEven td").css("background-color", "red");
alert($.fn.jquery);
/*$("#tableDg tbody tr:first").css({
"background-color": "red"
});*/
}
Here is my table
<div id="cdiv" style="width:100%;" spry:region="ds1">
<table id="tableDg"
style="border:#2F5882 1px solid;width:100%;" cellspacing="1" cellpadding="1">
<thead>
<tr id="trHead" style="color :#FFFFFF;background-color: #8EA4BB">
<th width="2%"><input id="chkbHead" type='checkbox' /></th>
<th width="10%" align="center" spry:sort="name"><b>Name</b></th>
<th width="22%" align="center" spry:sort="host"><b>Country</b></th>
</tr>
</thead>
<tbody spry:repeat="ds1">
<tr id="trOdd"
spry:if="({ds_RowNumber} % 2) != 0" onclick="ds1.setCurrentRow('{ds_RowID}');"
style="color :#2F5882;background-color: #FFFFFF" class="{ds_OddRow}">
<td><input type="checkbox" id="chkbTest" class = "chkbCsm"></input></td>
<td width="10%" align="center"> {name}</td>
<td width="22%" align="center"> {country}</td>
</tr>
<tr id="trEven"
spry:if="({ds_RowNumber} % 2) == 0" onclick="ds1.setCurrentRow('{ds_RowID}');"
style="color :#2F5882;background-color: #EDF1F5;" class="{ds_EvenRow}">
<td><input type="checkbox" class = "chkbCsm"></input></td>
<td id="tdname" width="10%" align="center"> {name}</td>
<td width="22%" align="center"> {country}</td>
</tr>
</tbody>
</table>
</div>
Am I going wrong somewhere, please guide me. Thanks :)
If I remember right, <tr> is only describing structure. <td> represents visual part of the table. Or this is how some browsers renders them.
Therefore $("#trEven td").css("background-color", "red") should work. And preferrably you should use classes instead of ids in these kind of cases where there may exist multiple instances.
Works for me (jsFiddle). What problems are you experiencing?
If your use classes instead of id's, you can use something like the following:
$('.trEven').each(function() {
$(this).css({"background-color": "red"});
});
See for reference: jQuery API - .each()
You shouldn’t be using ids for odd and even rows. id values are meant to be unique within the page.
So, I’d suggest:
<tr class="trOdd"
and:
<tr class="trEven"
and then:
$(".trEven")
If you really only want the first row in the table body to get a red background (as opposed to all the even ones), then your selector should be:
$("#tableDg tbody tr:first")

Categories

Resources