-1

Check this simple table:

const table = document.getElementById("table");

table.addEventListener('click', e => {
  if (e.target.tagName === 'BUTTON') {
    const affectedRow = e.target.closest('tr');
    table.removeChild(affectedRow);
  }
});
<table border="1" id="table">
  <tr>
    <td>row A</td>
    <td><button>delete row</button></td>
  </tr>
  <tr>
    <td>row B</td>
    <td><button>delete row</button></td>
  </tr>
  <tr>
    <td>row C</td>
    <td><button>delete row</button></td>
  </tr>
</table>

Trying to remove a row using table.removeChild(affectedRow) gives me

Uncaught DOMException: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.

Is using a tbody element mandatory?

Why are browsers auto-inserting a tbody element? I checked on validator.w3.org and omitting a tbody tag seems valid HTML.

How do I remove the row without using HTMLTableElement.prototype.deleteRow(index), using only HTMLElement.prototype methods and properties?

connexo
  • 53,704
  • 14
  • 91
  • 128

3 Answers3

2

You can check to see if the table has a tbody element beneath it, and if so, delete rows from underneath that element instead:

const table = document.getElementById("table");
const tbody = (table.firstElementChild.nodeName == 'TBODY' ? table.firstElementChild : table);

table.addEventListener('click', e => {
  if (e.target.tagName === 'BUTTON') {
    const affectedRow = e.target.closest('tr');
    tbody.removeChild(affectedRow);
  }
});
<table border="1" id="table">
  <tr>
    <td>row A</td>
    <td><button>delete row</button></td>
  </tr>
  <tr>
    <td>row B</td>
    <td><button>delete row</button></td>
  </tr>
  <tr>
    <td>row C</td>
    <td><button>delete row</button></td>
  </tr>
</table>
Nick
  • 138,499
  • 22
  • 57
  • 95
1

Use this way table.tBodies[0].removeChild

why?

tbody, thead and tfoot are inserted by all browsers even the champion IE does that, its the W3c spec.

The HTML Table Body element (tbody) encapsulates a set of table rows (tr elements), indicating that they comprise the body of the table (table) similarly the header and footer of the table.

joyBlanks
  • 6,419
  • 1
  • 22
  • 47
1

Many browsers add a <tbody> element to HTML tables, if one doesn't exist. You can read more about why on this post: Why do browsers insert tbody element into table elements?

removeChild() only removes children, not descendants. So if a <tbody> exists then the <tr> you're trying to remove is a child of <tbody>, and not a child of the <table> element.

You could do:

document.querySelector("#table tbody").removeChild(affectedRow);
JoshG
  • 6,472
  • 2
  • 38
  • 61
  • I see this came unexpected for you, too. I'd really like to understand if this is how it is supposed to behave and if so, why. Will I have to check whether in the browser the code is run in it has inserted a `tbody`? – connexo Aug 24 '19 at 08:32
  • @connexo See this post as to why browsers do this: https://stackoverflow.com/questions/938083/why-do-browsers-insert-tbody-element-into-table-elements – JoshG Aug 24 '19 at 08:32