How to add sub row in table on button click

人盡茶涼 提交于 2021-02-10 14:56:08

问题


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, add a new sub row inside the same genre,

On Group button click I can Add a new row and it works fine, but in any group, If I try to add 2+ genres, then the table layout gets messed up.

$(document).on('click', '#my_table button.2ndName', function() {
  var $row = $(this).closest("tr");

  var nrid = $row.find(".nr").attr('rowspan');

  if (nrid == null) {
    nrid = 1;
  }

  nrid++;
  $row.find(".nr").attr('rowspan', nrid);
  var newRow = $("<tr>");
  var cols = "";
  var $td = $(this).closest("td");
  $td.find("#btn").hide();

  cols += '<td><input type="text" placeholder="" size="13" /><button class="2ndName" id="btn">+</button></td>    <td><input type="text" placeholder="" size="7"></td><td><input type="text"placeholder="" size="7"></td><td><input type="text" placeholder="" size="7"></td"><td><input type="text" size="7" placeholder=""></td><td><input type="text" size="10" placeholder=""></td><td><input type="text" placeholder="" size="7"></td><td><input type="text" size="7" placeholder=""></td><td><input type="text" size="7" placeholder=""></td></tr>';
  newRow.append(cols);

  newRow.insertAfter($(this).parents().closest('tr'));

});

$(document).on('click', '#my_table button.site', function() {
  var $row = $(this).closest("tr");

  var newRow = $("<tr>");
  var cols = "";
  var $td = $(this).closest("td");
  $td.find("#btn").hide();

  cols += '<td class="nr"><input type="text" placeholder="" size="9"><button id="btn" class="site" style="float:right;">+</button></td><td><input type="text" placeholder="" size="13"><button class="2ndName" id="btn" style="float:right;">+</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>';
  newRow.append(cols);

  newRow.insertAfter($(this).parents().closest('tr'));

});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="my_table" id="my_table" border="1px" style="border-collapse: collapse;">

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

  <tr>
    <td class="nr"><input type="text" placeholder="" size="9"><button id="btn" class="site" style="float:right;">+</button>
    </td>
    <td><input type="text" placeholder="" size="13"><button class="2ndName" id="btn" style="float:right;">+</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>

</table>

回答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




回答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.



回答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.



来源:https://stackoverflow.com/questions/59942996/how-to-add-sub-row-in-table-on-button-click

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!