How to get data attribute of element when click on it or it child
Asked Answered
J

4

7

I am making a Table.

document.querySelector('table').addEventListener('click', (e) => {
  console.log(e.target);
  console.log(e.target.dataset.item);
})
td {
  padding: 8px;
  border: 1px solid black;
  background-color: blue;
}

span {
  background-color: red;
  padding: 4px;
}
<table>
  <tr>
    <td data-item="item1"><span>1</span></td>
    <td data-item="item2"><span>2</span></td>
    <td data-item="item3"><span>3</span></td>
    <td data-item="item4"><span>4</span></td>
    <td data-item="item5"><span>5</span></td>
  </tr>
</table>

When I click the BLUE PART, I can get data-item attribute. But when I click the RED PART, I can't.

I wanna fix it, if I click <span/> in <td/>, I want to get data-item attribute from <td />.

Jagged answered 12/12, 2018 at 12:58 Comment(1)
You could use e.target.closest("[data-item]").dataset.item, if supported.Stoneman
B
8

Try to use closest by your child tag instead of dataset.

document.querySelector('table').addEventListener('click', (e) => {
  console.log(e.target.closest("td").dataset.item);
})
td {
  padding: 8px;
  border: 1px solid black;
  background-color: blue;
}

span {
  background-color: red;
  padding: 4px;
}
<table>
  <tr>
    <td data-item="item1"><span>1</span></td>
    <td data-item="item2"><span>2</span></td>
    <td data-item="item3"><span>3</span></td>
    <td data-item="item4"><span>4</span></td>
    <td data-item="item5"><span>5</span></td>
  </tr>
</table>
Bubalo answered 12/12, 2018 at 13:3 Comment(2)
Thank you for you answer :)Jagged
this is the perfect answer what I found.Jagged
V
3

Check if name of clicked element is span select parent of it using parentNode property

document.querySelector('table').addEventListener('click', (e) => {
  var ele = e.target.nodeName == "SPAN" ? e.target.parentNode : e.target;
  console.log(ele.dataset.item);
})
td {
  padding: 8px;
  border: 1px solid black;
  background-color: blue;
}
span {
  background-color: red;
  padding: 4px;
}
<table>
  <tr>
    <td data-item="item1"><span>1</span></td>
    <td data-item="item2"><span>2</span></td>
    <td data-item="item3"><span>3</span></td>
    <td data-item="item4"><span>4</span></td>
    <td data-item="item5"><span>5</span></td>
  </tr>
</table>
Vivisection answered 12/12, 2018 at 13:3 Comment(1)
Thank you for your answer :)Jagged
M
0

Why do you listen on the whole table in the first place?

Listen only on "td" elements:

let cells = document.getElementsByTagName('td');
for (var i=0; i < cells.length; i++) {
  let cell = cells[i];
  cell.addEventListener('click', (e) => {
    let element = e.target.nodeName;
    if (element === 'TD') {
      console.log(e.target.dataset.item);
    } else if (element === 'SPAN') {
      console.log(e.target.parentNode.dataset.item);
    }      
  });
}

I don't think setting the listener on the table matters, because in your case, it doesn't trigger the event on the table anyways.

Some styles for better inspection:

table {
  background-color: orange;
  border-spacing: 10px;
}

https://jsfiddle.net/aleks351/p0b46wqs/6/

Matchbox answered 12/12, 2018 at 13:18 Comment(1)
because in my table, <tbody /> is dynamically renderedJagged
B
0

You could check for the keys in the dataset of the clicked item and if it does have some properties then use e.target otherwise move up one level e.target.parentNode:

document.querySelector('table').addEventListener('click', (e) => {
  var el = Object.keys(e.target.dataset).length ? 
           e.target: e.target.parentNode;
  console.log(el.dataset.item);
})
td {
  padding: 8px;
  border: 1px solid black;
  background-color: blue;
}

span {
  background-color: red;
  padding: 4px;
}
<table>
  <tr>
    <td data-item="item1"><span>1</span></td>
    <td data-item="item2"><span>2</span></td>
    <td data-item="item3"><span>3</span></td>
    <td data-item="item4"><span>4</span></td>
    <td data-item="item5"><span>5</span></td>
  </tr>
</table>
Befoul answered 12/12, 2018 at 13:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.