How do I get data set from a tr element - javascript

I was working on my react project and I put an onClick function and dataset to my <tr> element like this
<tr key={index} onClick={ev} data-ti={ddd.id} className={classs}>
and so in that ev function I tried to get the value from the dataset like this
function ev(e){
const {ti} = e.target.dataset
console.log(ti) // returns undefined
}
and instead of returning an id it returns undefined am I doing something wrong or maybe there's another way of doing it

It's likely that instead of clicking on the tr you're actually clicking on the td inside it. So you need to get the parentNode of that td first, and then grab the data attribute.
const tr = document.querySelector('tr');
tr.addEventListener('click', handleClick, false);
function handleClick(e) {
const { target: { parentNode } } = e;
const { dataset: { ti } } = parentNode;
console.log(ti);
}
<table>
<tbody>
<tr data-ti="test">
<td>Test</td>
</tr>
</tbody>
</table>
I'll add Rob's edit here.
const tr = document.querySelector('tr');
tr.addEventListener('click', handleClick, false);
function handleClick(e) {
const tr = e.target.closest('tr');
const ti = tr ? tr.dataset.ti : null;
console.log(ti);
}
<table>
<tbody>
<tr data-ti="test">
<td>Test</td>
</tr>
</tbody>
</table>

You can simply set the event inside your onClick with a variable of the value you want, like onClick={ev(ddd.id)}.

Related

Opacity 0 Javascript function

This is my first SO post, please let me know how to do better!
I have a function that clears the by setting the opacity to 0, it works, but it will make my file massive if if try to set up a whole spread sheet with each having the same function bar different ids,
Ideally, the way I want this to play out, is that clears itself, and will clear all blocks. And I want to do it without having to write duplicate functions.
Is it possible to have a function set over classes? I have tried with no success
Or is there a better way to run the JavaScript, like somehow onclick==clear.self ?
function Xf1() {
f1();
f2();
}
function f1() {
var element = document.getElementById("a1");
element.style.opacity = "0";
}
function f2() {
var element = document.getElementById("a2");
element.style.opacity = "0";
<tr>
<th onclick="Xf1()">Clear all</th>
</tr>
<tr>
<td onclick="f1()" id="a1"> text1</td>
<td onclick="f2()" id="a2"> text2</td>
</tr>
You can use event delegation
start by adding a class to the table element
add a class to the "clear all" heading
add a click event listener to the table element
If the click event target is a td element, set its opacity to 0.
If the click target is the clear all heading, set all td elements to opacity 0. You can do that by querying the table for td tags and then using forEach to change the opacity for each of them.
const myTable = document.body.querySelector(".my-table");
myTable.addEventListener("click", event => {
const target = event.target;
if (target.tagName == "TD") {
target.style.opacity = 0;
}
if (target.classList.contains("clear-all")) {
myTable.querySelectorAll("td").forEach(item => (item.style.opacity = 0));
}
});
<table class="my-table">
<thead>
<th class="clear-all">Clear all</th>
</thead>
<tbody>
<tr>
<td id="a1">text1</td>
<td id="a2">text2</td>
</tr>
</tbody>
</table>
set an id to parent tag then set onclick to that elements children.
if you set "container" as id you will have something like this:
var elements = document.getElementById("container");
for (let i = 0; i < elements.children.length; i++) {
elements.children[i].onclick = function () {
elements.children[i].style.opacity = "0";
};
}
Instead of adding onclick to each td element. Have it in table element. Like this
document.querySelector("#table").addEventListener("click", (event)=>{
if(event.target.dataset.type==='clear'){
const ids = ['a1', 'a2'];
ids.forEach((ele)=>{
document.querySelector(`#${ele}`).style.opacity = '0';
});
return;
}
event.target.style.opacity = "0";
}
)
<table id="table">
<tr>
<th data-type="clear">Clear all</th>
</tr>
<tr id="tableRows">
<td id="a1"> text1</td>
<td id="a2"> text2</td>
</tr>
</table>

Highlight html td by diffrent color when cell value is greater than specific value

I try to change the row color when it's td cell value is greater than 10, nevertheless at the moment all rows become highlight when hover is done on Darksalmon color and no Red when value is > 10. What i am doing wrong?
Additional question: My html table has 5 columns, i do not want last one to be highlited. How to exclude such column?
CSS:
<style type="text/css">
tr {
background: #fff;
}
tr:hover {
background: darksalmon;
}
</style>
JS:
<script type="text/javascript">
function Highlight(row) {
if(document.getElementById("price").value > 10)
{
document.getElementById(row).style.background = 'Red';
}
else
{
document.getElementById(row).removeAttribute("style");
document.getElementById(row).onMouseOver = function () { this.className = "hover"; }
}
}
</script>
Html:
<table>
<tr id="row1" onmouseover="javascript:Highlight('row1');">
<td id="price"></td>
</tr>
<table>
There are a lot of things wrong:
HTML:
You should close the table tag </table>.
Don't give your table rows and table cells an id. Give your table body or table an idea for example:
<table>
<thead>
<tr>
<th>Price</th>
</tr>
</thead>
<tbody id="tbody">
<tr>
<td>2</td>
<td>3</td>
<td>11</td>
<td>13</td>
<td>5</td>
</tr>
</tbody>
</table>
JS:
const tableBody = document.getElementById("tbody"); // get your table body or table if you don't want a table body
const rows = tableBody.getElementsByTagName("tr"); // get all your table rows inside your table body
// loop through all your tr elements
for (let i = 0; i < rows.length; i++) {
// here it is probably best to get the td element but because there is only one column there is no need for this.
// if there are more then 1 columns get the td element like this const td = rows[i].firstElementChild; if it is
// the first otherwise give them a class and get them with getElementsByClassName[0] on the rows[i]
// try to parse the innerText of the td or tr element to an integer (Number) because if there is text this will throw an exception
try {
// if price > 10 make background color of row red otherwise darkSalmon
if (parseInt(rows[i].innerText) > 10) {
rows[i].style.backgroundColor = "red";
}
else {
rows[i].style.backgroundColor = "darksalmon";
}
}
catch (e) {
console.error(e);
}
//if you want to do this on mousover you can add event listeners per row
rows[i].addEventListener("mouseover", () => {
try {
// if price > 10 make background color of row red otherwise darkSalmon
if (parseInt(rows[i].innerText) > 10) {
rows[i].style.backgroundColor = "red";
}
else {
rows[i].style.backgroundColor = "darksalmon";
}
}
catch (e) {
console.error(e);
}
});
//if you want to set the background color back on default when your mouse leaves the tr do this
rows[i].addEventListener("mouseleave", () => {
rows[i].style.backgroundColor = null;
});
}
I hope this is detailed enough for you, otherwise I suggest reading some basic tutorials on w3schools or a platform like that.

Using Conditional If statements with JavaScript DOM Table?

I have been given a table that has been created using the DOM and now I have to use if statements to print specific areas of that table. For example in the second photo, when i click 1 - 2 million, it should show the table but only display the countries that have a population that's between 1 and 2 million. My teacher has barely taught us JavaScript deeply and now gives us a DOM assignment that uses JavaScript If Statements. I would appreciate if someone could give an explanation on how i can print specific parts of the table when i click the links/button above. Thanks!
Here a roadmap:
Loop through your submenus with a for (or for ... in) statement and attach a click event listener on each one with addEventListener()
In the callback, this will refer to the <li> (or <a>, or whatever) element you clicked (and which is linked to an event). So you can access the DOM clicked element's data nor attributes.
In function of the clicked submenu, filter your <table> the way you want thanks to if statements. (even better: switch statement) Visually, rows will be hidden. In Javascript, you will update style attribute of the element.
Below an example. I propose to you to try to do it yourself with elements I gave you. Open the snippet if you are really lost.
Exemple:
Other functions/methods/statements I used below: querySelectorAll(), dataset, instanceof, parseInt(), onload, children
// Always interact with the DOM when it is fully loaded.
window.onload = () => {
// Gets all <button> with a "data-filter-case" attribute.
const buttons = document.querySelectorAll('button[data-filter-case]');
// For each <button>, attach a click event listener.
for (let i in buttons) {
const button = buttons[i];
// The last item of "buttons" is its length (number), so we have to check if
// it is a HTMLElement object.
if (button instanceof HTMLElement) {
button.addEventListener('click', filterTable); // Will execute the "filterTable" function on click.
}
}
}
// The function which will filter the table.
function filterTable(e) {
// Useless in my exemple, but if you have <a> instead of <button>,
// it will not execute its original behavior.
e.preventDefault();
// Get the value of "data-filter-case" attribute.
const filterCase = this.dataset.filterCase;
// Get all table body rows.
const tableRows = document.querySelectorAll('table > tbody > tr');
// Update display style of each row in function of the case.
for (let i in tableRows) {
const row = tableRows[i];
if (row instanceof HTMLElement) {
if (filterCase === 'more-than-44') {
if (parseInt(row.children[1].innerText) <= 44) {
// Hide the row.
row.style.display = 'none';
} else {
// Reset display style value.
row.style.display = '';
}
} else if (filterCase === 'less-than-27') {
if (parseInt(row.children[1].innerText) >= 27) {
row.style.display = 'none';
} else {
row.style.display = '';
}
} else if (filterCase === 'reset') {
row.style.display = '';
}
}
}
}
<button type="button" data-filter-case="more-than-44">More than 44</button>
<button type="button" data-filter-case="less-than-27">Less than 27</button>
<button type="button" data-filter-case="reset">Show all</button>
<table>
<thead>
<tr>
<th>ID</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<th>1</th>
<td>45</td>
</tr>
<tr>
<th>2</th>
<td>50</td>
</tr>
<tr>
<th>3</th>
<td>24</td>
</tr>
</tbody>
</table>

Can not set focus on a table row

I am trying to set a focus on a table row at component initialization and i get a null when using interop
<table class='table'>
<thead>
<tr>value</tr>
</thead>
<tbody>
#foreach (var elem in this.data) {
<tr id="#elem.toString()"><td>#elem</td></tr>
</tbody>
</table>
#functions()
{
protected int []data=new int[]{1,2,3,34};
protected override async Task OnInitAsync() {
if (data.Length > 0) {
var elementName= data.First().ToString();
await JSRuntime.Current.InvokeAsync<string>("methods.focus", elementName);;
}
}
}
Interop
window.methods={
focus: function (elementName) { //i get the right id
var element = document.getElementById(elementName);//returns null
element.focus();
}
}
P.S I get the right elementName in the focus method when debugging in the browser but document.getElementByIdreturns a null element.Do i need to first get the table element and then search the row in it ?
You cannot set the focus on a td or tr elements. However, you can place an input element within the td element and then set the focus.
Hope this helps...

Assigning an event to a <td> cell via a function

I'm trying to understand why I can add certain items to a cell, such as 'id', and not other items such as an onclick. My goal is to have a button pressed, which adds a row to a table (which works) - and set some values on the that is generated/appended to the table. I've noticed that I can step into the console and do:
rows[row_#].cells[cell_#].id = 'foo';
and have it appear in the table on the and function; but the following will not appear on the :
rows[row_#].cells[cell_#].onclick = 'callEvent(this)';
Should I be assigning this differently?
<button type="button" id="btn_add_row" onclick="addRow()">Add Row</button>
<table class="table table-hover" id="sample_table">
<thead>
<th>Column A</th>
<th id='calculate'>Column B</th>
</thead>
<tbody>
<tr>
<td>Item 1</td>
//sample of the td I'd like the function to generate
<td id='calculate' onclick='callEvent(this)'>Item 2</td>
</tr>
</tbody>
</table>
<script type="text/javascript">
// Code to add a row to the table and assign properties to new row
function addRow() {
var table = document.getElementById("sample_table");
var lastRow = table.length;
var numberOfCols = table.rows[0].cells.length;
var row = table.insertRow(lastRow);
for (var i=0;i<numberOfCols;i++) {
row.insertCell(i);
if (table.rows[0].cells[i].id === 'calculate') {
// The calculate id will appear on the TD after running
table.rows[i].id = 'calculate';
// The onclick event will not appear on the TD afer running
table.rows[i].onclick='callEvent(this)';
}
function callEvent(element) {
console.log('Calculate event fired!');
}
</script>
The biggest issue is that you are not supplying a callback function reference to your onclick property. You are supplying a string:
.onclick='callEvent(this)'
So, no function actually gets invoked when the click event occurs.
Next, you shouldn't be using event properties (like onclick) in your JavaScript or adding inline HTML event handling attributes at all (that technique is about 20 years old) as they:
Create "spaghetti code" that is difficult to read and debug.
Lead to duplication of code.
Don't scale well
Don't follow the separation of concerns development methodology.
Create anonymous global wrapper functions around your attribute values that alter the this binding in your callback functions.
Don't follow the W3C Event Standard.
Instead, do all your work in JavaScript and use .addEventListener() to set up event handlers.
Also (FYI) id attributes need to be unique, so when you create a new row or cell, don't reuse an already assigned id.
Here's an example:
// Place all of this inside of a <script> element that is just before the
// closing of the body (</body>)
// Get references to all elements that you'll be working with
var btnAddRow = document.getElementById("btn_add_row");
var tbl = document.getElementById("sample_table");
// Now, set up the event handling functions
btnAddRow.addEventListener("click", addRow);
// Code to add a row to the table and assign properties to new row
function addRow() {
var counter = 1; // id attributes must be unique. This will keep it that way.
var numberOfCols = tbl.rows[0].cells.length;
var row = tbl.insertRow();
for (var i = 0; i < numberOfCols; i++) {
var cell = row.insertCell(i);
cell.id = "row" + (tbl.rows.length - 1) + "cell" + counter;
// Now, we'll create a new button, place that button in the new cell and
// set up a click event handler for it.
var btn = document.createElement("button");
btn.textContent = cell.id;
btn.id = "btn" + tbl.rows.length + counter;
// Add a click event handler
btn.addEventListener("click", function(){
alert("You clicked cell: " + this.id);
});
// And now include the button in the cell
cell.appendChild(btn);
counter++; // Increment the counter after using it
}
}
td { border:1px solid black; }
td:nth-child(2) { cursor:pointer; }
<button type="button" id="btn_add_row">Add Row</button>
<table class="table table-hover" id="sample_table">
<thead>
<th>Column A</th>
<th id='calculate'>Column B</th>
</thead>
<tbody>
<tr>
<td>Item 1</td>
<!-- sample of the td I'd like the function to generate -->
<td id='calculate'>Item 2</td>
</tr>
</tbody>
</table>
Two things:
The onclick expects a function. So to solve your problem, change
table.rows[i].onclick='callEvent(this)';
to
table.rows[i].onclick=callEvent;
The second thing is, the parameter on an event is actually the event, and this refers to the element:
function callEvent(event) {
console.log('Calculate event fired!');
// "event" is the event
// "this" is the element
}
missing need to second bracket end and use this callEvent(this) without single inverted comma.
Like this...
<script type="text/javascript">
// Code to add a row to the table and assign properties to new row
function addRow() {
var table = document.getElementById("sample_table");
var lastRow = table.length;
var numberOfCols = table.rows[0].cells.length;
var row = table.insertRow(lastRow);
for (var i=0;i<numberOfCols;i++) {
row.insertCell(i);
if (table.rows[0].cells[i].id === 'calculate') {
// The calculate id will appear on the TD after running
table.rows[i].id = 'calculate';
// The onclick event will not appear on the TD afer running
table.rows[i].onclick=callEvent(this);
}
}
}
function callEvent(element) {
console.log('Calculate event fired!');
}
</script>

Categories