Get column value onClick in nested HTML Table [Javascript] - 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>

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")

How do I filter a table by any matching code/name and not every available field

I'm trying to do the following: I have a table populated with data from the DB. Apart from that, I have an input where you can write something and a button that will filter, only showing the lines that have that string. This is working now!
The thing is, the input should only allow you to filter by foo.name/foo.code (two propertys of my entity).
I'm adding the code I have in case anyone can guide me out, I've tried several things but this are my first experiences with JQuery while I have a strict story-delivery time. Thanks everyone!
<tbody>
<c:forEach var="foo" items="${foo}">
<tr id = "fooInformation" class="mtrow">
<th id="fooName" scope="row">${foo.name}</th>
<td id="fooCode" class="left-align-text">${foo.code}</td>
<td class="left-align-text">${foo.country}</td>
<td class="left-align-text">${foo.region}</td>
<td class="left-align-text">${foo.subregion}</td>
</tr>
</c:forEach>
</tbody>
$("#search").click(function () { -> button id
var value = $("#fooRegionSearch").val(); -> value of the input
var rows = $("#fooRegionTable").find("tr"); -> table id
rows.hide();
rows.filter(":contains('" + value + "')").show();
});
To start with, your HTML is invalid - there cannot be elemenets with duplicate IDs in HTML. Use classes instead of IDs.
Then, you need to identify which TRs pass the test. .filter can accept a callback, so pass it a function which, given a TR, selects its fooName and fooCode children which contain the value using the :contains jQuery selector:
$("#search").click(function() {
var value = $("#fooRegionSearch").val();
var rows = $("#fooRegionTable").find("tr");
rows.hide();
rows.filter(
(_, row) => $(row).find('.fooName, .fooCode').filter(`:contains('${value}')`).length
).show();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="fooRegionTable">
<tr id="fooInformation" class="mtrow">
<th class="fooName" scope="row">name1</th>
<td class="fooCode" class="left-align-text">code1</td>
<td class="left-align-text">${foo.country}</td>
<td class="left-align-text">${foo.region}</td>
<td class="left-align-text">${foo.subregion}</td>
</tr>
<tr id="fooInformation" class="mtrow">
<th class="fooName" scope="row">name2</th>
<td class="fooCode" class="left-align-text">code2</td>
<td class="left-align-text">${foo.country}</td>
<td class="left-align-text">${foo.region}</td>
<td class="left-align-text">${foo.subregion}</td>
</tr>
</table>
<button id="search">click</button><input id="fooRegionSearch" />

Live search in table for specific column

I'm currently trying to create a live search for a specific column in a table. I've searched a bit but I can only find solutions to search over all columns. This is my code:
function searchInTable(table) {
var value = this.value.toLowerCase().trim();
jQuery(table).each(function (index) {
if (!index) return;
jQuery(this).find("td").each(function () {
var id = $(this).text().toLowerCase().trim();
var not_found = (id.indexOf(value) == -1);
$(this).closest('tr').toggle(!not_found);
return not_found;
});
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="search-table-input" class="search-table-input" type="text"
onkeyup="searchInTable('.table tr')" placeholder="Search Number...">
<table class="table">
<thead>
<tr>
<th class="table-number">
<span class="nobr">Number</span>
</th>
<th class="table-date">
<span class="nobr">Date</span>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<a>264</a>
</td>
<td>
<span>2019-01-02</span>
</td>
</tr>
<tr>
<td>
<a>967</a>
</td>
<td>
<span>2019-01-02</span>
</td>
</tr>
<tr>
<td>
<a>385</a>
</td>
<td>
<span>2019-01-02</span>
</td>
</tr>
<tr>
<td>
<a>642</a>
</td>
<td>
<span>2019-01-02</span>
</td>
</tr>
</tbody>
</table>
My function has some errors and don't work like it should.
How can I change my function that way that when I start typing only the number gets filtered? I need to make the function dynamically so that I can pass the column which should be used for the search.
The line that's causing it to search over all the columns is this one:
jQuery(this).find("td").each(function () {
...which takes each cell in the current row and looks to see if it contains value. If you only want to check as specific column, you should pass in the column index as something like columnIndex, and then you can select the correct column by doing jQuery(this).find("td").eq(columnIndex), using jQuery's .eq() function to select the correct one. The code should look something like this:
function searchInTableColumn(table, columnIndex) {
//check this.value exists to avoid errors
var value = this.value ? this.value.toLowerCase().trim() : "";
jQuery(table).each(function (index) {
if (!index) return;
var tableCell = jQuery(this).find("td").eq(columnIndex);
var id = tableCell.text().toLowerCase().trim();
var not_found = (id.indexOf(value) == -1);
$(this).closest('tr').toggle(!not_found);
});
}
Then you can call searchInTableColumn(table, 0) and it will only look in the first column.

Javascript Checkbox From a Table Returning Undefined

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;

Selector and Iterating Through a Table Within a Div

I have been working on this and cannot get this iterator to work. I have the following HTML and am trying to iterate through all rows (except the first row) and extract the values in cells (td) 2 and 3 :
<div id="statsId">
<table width="220" cellspacing="0" cellpadding="0" border="0">
<tbody>
<tr>
<td width="65"/>
<td width="90"/>
<td width="65"/>
</tr>
<tr style="font-weight: bold;">
<td align="left">$1.00</td>
<td>
UserID1
</td>
<td>Single</td>
</tr>
<tr>
<td align="left">$6.99</td>
<td>
UserID2
</td>
<td>Multiple</td>
</tr>
<tr>...
.....(snip)
I tried the following iterator to iterate through all except the first row of the table that is a child of "div#statsID" and get the values of the 2nd and 3rd cells (in the example, the first extracted cells would have values of "UserID1" and "Single"), but it doesn't work.
$('div#statsId > table tr:not(:nth-child(1))').each(function(i, ele) {
var secondCol = $('td:nth-child(2)', ele).innerHTML
var thirdCol= $('td:nth-child(3)', ele).text()
.....
});
Any suggestions on how to specify and iterate through the rows (except the first) of a table that is a child of a div would be appreciated.
$("#statsId > table tbody tr:not(:first)").each ( function() {
var secondCol = $(this).find('td:nth-child(2)').html();
var thirdCol= $(this).find('td:nth-child(3)').text();
});
Note
You can use the id selector independently. No need to use the tag name.
There is no innerHTML for a jQuery object. Use html() instead

Categories

Resources