javascriptjqueryexpandable-table

Expandable row for dynamic table


In my Reactjs Application I am having a table. I am using javascript's map function to fill the rows. That means my rows are rendered dynamically. This how I do it

<tbody>
  { this.state.MediaFiles.map((item, i) => (
  <tr id={i}>
    <td className="v-align-middle">
      <div className="checkbox">
        <input type="checkbox" value="3" id={ "checkbox1" + i}/>
        <label htmlFor={ "checkbox1" + i} onClick={()=> this.handleCheckboxClick(i,item.url, item.poster.list_thumbnail)}/>
      </div>
    </td>
    <td className="v-align-middle semi-bold">
      <div className='file-image'
      style={{backgroundImage: `url('${item.poster.list_thumbnail}')`}}/>
        <div className="movie-title">
          <span className="movie-name">
            <a onClick={this.showVideo(item.url, item.file, item.id, item.title, item.duration, item.height, item.width, item.frame_rate)}>{item.title}</a>
          </span>
          <br/>
          <span className="movie-info">Movie Trailer</span>
        </div>
      </td>

      <td className="v-align-middle text-success"> {this.jobStatus(item.job_status)}</td>
    </tr>
   ))
  }
</tbody>

Now I want each row of this table to be expandable.

I have tried the first answer of this question Can a table row expand and close?

Problem: My problem with the answer in above question's link is, it does not render the table rows by mapping it to some data. I do it by mapping. So in my map function, I cannot include two rows. When I try to, the syntax gets wrong as expected.

What I tried: I tried to put the two (s) in a div inside map function. But that just screws the css of table row. The two rows I am talking about is "the main row" and the "hidden row" which will get open when main row is clicked.

How should I do it.


Solution

  • If you need to add multiple tr's in mapping, then you have to use multiple 'tbody' as mentioned by @trevorgk in this answer.

    Another method is to dynamically add a row which should be displayed initially, thereby hiding the row, created using the mapping function. You can use some css for this

    <tbody>
    {
        this.state.MediaFiles.map((item, i) => (
            <tr id={i}>
                <td className="v-align-middle">
                    .
                    .
                    your rest code goes here
                    .
                    .           
        ))
    }
    </tbody>
    

    Now using jquery add the rows, that need to be displayed initially. And handle the remaining part with you click event.

    A small working model (mapping part is not included) is given below.

    $(function() {
      $('tr.content-row').each(function() {
        $(this).before($('<tr><td class="view-me">View this row</td></tr>'));
      });
    });
    $(document).on('click', '.view-me', function() {
      $(this).closest('tr').next('tr.content-row').toggleClass('hidden');
    });
    .hidden {
      display: none;
    }
    
    .view-me {
      cursor: pointer;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <table>
      <tr class="hidden content-row">
        <td>Row 1</td>
      </tr>
      <tr class="hidden content-row">
        <td>Row 2</td>
      </tr>
      <tr class="hidden content-row">
        <td>Row 3</td>
      </tr>
    </table>