Skip to content Skip to sidebar Skip to footer

How To Add Sub Row In Table On Button Click

I'm trying to create a dynamic table where I can add rows and Sub rows on button click. Currently I have 2 features: on Group button click, add a new row, on Genre button click, a

Solution 1:

well... I done it with JS

const myTable = document.querySelector('#my-table tbody')   // Where it all happens
  ,   RowBase = myTable.querySelector('tr').cloneNode(true) // Copy ref for each new line
  ;
myTable.querySelector('tr button.onGenre').TD_Group = myTable.querySelector('tr td')  // tell him who it belongs to
  ;
myTable.onclick=e=>   // for any click on the table
  {
  if (!e.target.matches('button.onGroup, button.onGenre')) return // except the others

  let OnButton = e.target                 // and Adam named each thing...
    , newRow   = RowBase.cloneNode(true)  // future new row
    ;
  if (OnButton.className==='onGroup')     // it's him !
    {
    newRow.querySelector('tr button.onGenre').TD_Group = newRow.querySelector('tr td') // this one belong to the new
    myTable.appendChild( newRow )
    }
  else // (OnButton.className==='onGenre')      // it's the other !
    {
    newRow.querySelector('td').remove()                                    // remove <td...  button class="onGroup" ...td>
    newRow.querySelector('tr button.onGenre').TD_Group = OnButton.TD_Group // this one belong where is his reference onGroup

    let nRowSp = parseInt(OnButton.TD_Group.getAttribute('rowspan')) +1    // compute new val for rowspan
    OnButton.TD_Group.setAttribute('rowspan', nRowSp )                     // put it on

    OnButton.parentNode.parentNode.insertAdjacentElement('afterend',newRow )  // to add  the new row in the right place
    }
  OnButton.remove();  // that's the law: any clicked button must disappear!
  }


/* ----------------------------------------------------- *\
|  special delivery -> how to recover the entered values  |
\* ----------------------------------------------------- */ 

const ColsNames = [...document.querySelectorAll('#my-table thead td')].map(e=>e.textContent)  // get all columns names
  ,   ColsN_Nb  = ColsNames.length            // will not change, so much to know right away
  ;
document.getElementById('Bt-get-table-inputs').onclick=_=>  // I did not find a simpler name
  {
  let Resp    = []    // future solution
    , Grp_id  = 0     // we always need a reference
    , Grp_Elm = null  // out of respect for gregarious nature
    ;
  myTable.querySelectorAll('tr').forEach(xTR=>   // get each row
    {
      let inVals = xTR.querySelectorAll('input') // get all inputs
        , newGrp = (inVals.length === ColsN_Nb)  // if inputs numbers is full, or not
        ;
      if (newGrp) 
        {
        Grp_id++  // set new ref
        Resp.push( { id:Grp_id, Group:inVals[0].value, elm:[] } ) 
        Grp_Elm = Resp[(Grp_id-1)].elm  // everything will belong to him
        }
      let vals = {}
      inVals.forEach((inV,i)=>
        {
        if (!newGrp)   vals[ ColsNames[i+1]] = inV.value
        else if (i>0)  vals[ ColsNames[i]]   = inV.value
        })
      Grp_Elm.push( vals )
    })

  console.log(JSON.stringify(Resp,0,2 )  )  // for testing
  }
#my-table {
  margin-top: 3em;
  border-collapse : collapse;
  font-family     : Arial, Helvetica, sans-serif;
  font-size       : 14px;
}
#my-table thead td {
  background-color : turquoise;
  text-align       : center;
  padding          : .7em 0;
  white-space      : nowrap;
}
#my-table tbody td {
  width          : 1em;
  vertical-align : top;
} 
#my-table td           { border           : 1px solid gray; } 
#my-table tbody        { background-color : lightsteelblue; }
#my-table tbody button { float            : right;            }

/* just to test snippet  */
#Bt-get-table-inputs { position: fixed; top:0.5em; left:1em }
.as-console-wrapper { max-height: 100% !important; width: 40% !important; top: 0; left: 60% !important; }
<table id="my-table">
  <thead>
    <tr>
      <td>Group</td><td>Genre</td><td>Movie Name</td><td>Imdb</td><td>Rotten Tomato</td>
      <td>Lead Actress</td><td>Lead Actor</td><td>Year of Release</td><td>Revenue</td><td>Budget</td>
    </tr>      
  </thead>
  <tbody>
    <tr>
      <td rowspan="1"><input type="text" size="9"  placeholder=""><button class="onGroup"> + </button></td>
      <td><input type="text" size="13" placeholder=""><button class="onGenre" > + </button></td>
      <td><input type="text" size="7"  placeholder=""></td>
      <td><input type="text" size="7"  placeholder=""></td>
      <td><input type="text" size="7"  placeholder=""></td>
      <td><input type="text" size="7"  placeholder=""></td>
      <td><input type="text" size="10" placeholder=""></td>
      <td><input type="text" size="7"  placeholder=""></td>
      <td><input type="text" size="7"  placeholder=""></td>
      <td><input type="text" size="7"  placeholder=""></td>
    </tr>
  </tbody>
</table>

<!-- Just for test getting values -->
<button id="Bt-get-table-inputs">Get All values</button>

I don't think it can be done that simply with jQuery ;)
Full screen is better to show snippet


Solution 2:

your problem is quite simple to solve. This is my mini version of what you have here.

Basically the problem is this:

  • You have your code to update the rowspan of the group cell. However, this only works if you are still on the same row (or first insert). On the second insert, since you don't have the group cell anymore, your code fails.

Some extra tips:

  • If you are planning to go with jQuery, maybe learn about element creation using jQuery (I did that in my link), I think it will make your code looks clearer
  • Have proper string for id and class. That will help you distinguish things easier.

Solution 3:

The rowspan is not updating each time you click on the 'button.2ndName" it's only happening first time where it sets to rowspan=2 that's why it's working for the first two rows.


Post a Comment for "How To Add Sub Row In Table On Button Click"