skip to Main Content

Im loading row detail information in a bootstrap table via an Ajax call with the id as parameters .
This details show within a collapsible row using a glyph icon button.

However,clicking back on the button to collapse the row end up in distorting the display.
I’ve been struggling to find a fix to it although the code seems correct.
May you find the jsFiddle here

var parentsData = {
  "success": true,
  "parents": [{
    "id": 1531,
    "Firstname": "Austin",
    "Surname": "Anau00eblle",
    "schoolId": "046039",
    "schoolName": "ARCAMBAL",
    "commune": "ARCAMBAL"
  }, {
    "id": 2032,
    "Firstname": "Ramos",
    "Surname": "Lu00e8i",
    "schoolId": "046043",
    "schoolName": "J CALVET",
    "commune": "CAHORS"
  }, {
    "id": 3036,
    "Firstname": "Baker",
    "Surname": "Salomu00e9",
    "schoolId": "046043",
    "schoolName": "Z LAFAGE",
    "commune": "CAHORS"
  }, {
    "id": 1724,
    "Firstname": "Berry",
    "Surname": "Marlu00e8ne",
    "schoolId": "046044",
    "schoolName": "J CALVET",
    "commune": "CAHORS"
  }]
};

var $table = $('.js-table');
$table.find('.js-view-parents').on('click', function(e) {
  e.preventDefault();
  if (!$(this).closest('tr').next('tr').hasClass('expand-child')) {

    $(e.target).toggleClass('glyphicon-eye-close glyphicon-eye-open');

    $(".expand-child").slideUp();
    var $this = $(this).closest('tr');
    var rowId = $(this).data('id');

    var newRow = '<tr class="expand-child">' + '<td colspan="12" id="collapse' + rowId +
      '">' +
      '<table class="table table-condensed table-bordered" width=100% >' +
      '<thead>' +
      '<tr>' +
      '<th>Surname</th>' +
      '<th >FirstName</th>' +
      '<th >School Id</th>' +
      '<th >School name</th>' +
      '</tr>' +
      '</thead>' +
      '<tbody>';

    $.ajax({
      url: '/echo/json/',
      dataType: "json",
      data: parentsData,
      success: function(parentsData) {
        if (parentsData.parents) {
          var parents = parentsData.parents;
          $.each(parents, function(i, parent) {
            newRow = newRow + '<tr scope="row">' +
              '<td>' + parent.Firstname + '</td>' +
              '<td>' + parent.Surname + '</td>' +
              '<td>' + parent.schoolId + '</td>' +
              '<td>' + parent.schoolName + ' ' + parent.commune +
              '</td>' +
              '</tr>';
          });
          newRow = newRow + '</tbody></table></td></tr>';
        }
        $(newRow).insertAfter($this);
      }
    });
  } else {
    $(this).closest('tr').slideToggle();
    var $detailRow = $(this).closest('tr').next('tr').hasClass('expand-child');
    $detailRow.style.visibility.toggle('table-row collapse');
    $(e.target).toggleClass('glyphicon-eye-close glyphicon-eye-open');
  }
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<container>
  <table class="table table-striped table-hover js-table">
    <thead>
      <tr>
        <th>Training</th>
        <th>Title</th>
        <th>Date</th>
        <th>End date</th>
        <th>Description</th>
        <th>nb of Applicants</th>
        <th>Actions</th>
      </tr>
    </thead>
    <tr data-toggle="collapse" data-target="#collapse4039" class="clickable">
      <td>Activités nautiques</td>
      <td>Activités nautiques - 16/10/2016</td>
      <td>16/oct./2016</td>
      <td>13/oct./2016</td>
      <td>Sequelae of viral hepatitis</td>
      <td>15</td>
      <td>
        <div class="btn-group btn-group-sm" role="group" aria-label="...">
          <div class="btn-group " role="group" aria-label="Voir le detail">
            <a href="#" class="parents js-view-parents" data-href="formation_json_parents" data-id=4039 data-toggle="tooltip" data-placement="top" alt="Voir les details" title="Voir les inscrits">
              <span class="glyphicon glyphicon-eye-close" aria-hidden="true" style="color:black; margin: 5px;"></span>
            </a>
          </div>

          <div class="btn-group " role="group" aria-label="Valider les candidats">
            <a href="valider" data-href='' alt="Valider les candidats" data-toggle="tooltip" data-placement="right" title="Valider les candidats">
              <span class="glyphicon glyphicon-check" aria-hidden="true" style="color:black; margin: 5px;"></span>
            </a>
          </div>
          <div class="btn-group " role="group" aria-label="Imprimer la liste d'emargement pour cette formation">
            <a href="/edsa-AgrementEPS/app_dev.php/formation/4039/liste?print=pdf" data-href="" alt="Download PDF list of applicants" data-toggle="tooltip" data-placement="right" name="Activités nautiques - 16/10/2016" title="Download PDF list of applicants">
              <span class="glyphicon glyphicon-download-alt" aria-hidden="true" style="color:black; margin: 5px;"></span>
            </a>
          </div>
        </div>
      </td>
    </tr>
    <tr data-toggle="collapse" data-target="#collapse4095" class="clickable">
      <td>Activités nautiques</td>
      <td> Activités nautiques - 24/10/2016</td>
      <td>24/oct./2016</td>
      <td>21/oct./2016</td>
      <td>Severe pre-eclampsia, third trimester</td>
      <td>0</td>
      <td>
        <div class="btn-group btn-group-sm" role="group" aria-label="...">
          <div class="btn-group hidden" role="group" aria-label="Voir le detail">
            <a href="#" class="parents js-view-parents" data-href="formation_json_parents" data-id=4095 data-toggle="tooltip" data-placement="top" alt="Voir les details" title="Voir les inscrits">
              <span class="glyphicon " aria-hidden="true" style="color:black; margin: 5px;"></span>
            </a>
          </div>

          <div class="btn-group hidden" role="group" aria-label="Valider les candidats">
            <a href="/valider" data-href='' alt="Valider les candidats" data-toggle="tooltip" data-placement="right" title="Valider les candidats">
              <span class="glyphicon glyphicon-check" aria-hidden="true" style="color:black; margin: 5px;"></span>
            </a>
          </div>
          <div class="btn-group hidden" role="group" aria-label="Imprimer la liste d'emargement pour cette formation">
            <a href="/print=pdf" data-href="" alt="Download PDF list of applicants" data-toggle="tooltip" data-placement="right" name="Activités nautiques - 24/10/2016" title="Download PDF list of applicants">
              <span class="glyphicon glyphicon-download-alt" aria-hidden="true" style="color:black; margin: 5px;"></span>
            </a>
          </div>
        </div>
      </td>
    </tr>
    <tr data-toggle="collapse" data-target="#collapse3188" class="clickable">
      <td>Activités nautiques</td>
      <td>Activités nautiques - 29/10/2016</td>
      <td>29/oct./2016</td>
      <td>26/oct./2016</td>
      <td>Other secondary chronic gout</td>
      <td>0</td>
      <td>
        <div class="btn-group btn-group-sm" role="group" aria-label="...">
          <div class="btn-group " role="group" aria-label="Voir le detail">
            <a href="#" class="parents js-view-parents" data-href="formation_json_parents" data-id=4039 data-toggle="tooltip" data-placement="top" alt="Voir les details" title="Voir les inscrits">
              <span class="glyphicon glyphicon-eye-close" aria-hidden="true" style="color:black; margin: 5px;"></span>
            </a>
          </div>

          <div class="btn-group " role="group" aria-label="Valider les candidats">
            <a href="valider" data-href='' alt="Valider les candidats" data-toggle="tooltip" data-placement="right" title="Valider les candidats">
              <span class="glyphicon glyphicon-check" aria-hidden="true" style="color:black; margin: 5px;"></span>
            </a>
          </div>
          <div class="btn-group " role="group" aria-label="Imprimer la liste d'emargement pour cette formation">
            <a href="/liste?print=pdf" data-href="" alt="Download PDF list of applicants" data-toggle="tooltip" data-placement="right" name="Activités nautiques - 16/10/2016" title="Download PDF list of applicants">
              <span class="glyphicon glyphicon-download-alt" aria-hidden="true" style="color:black; margin: 5px;"></span>
            </a>
          </div>
        </div>
      </td>
    </tr>

  </table>
</container>

2

Answers


  1. There are several things wrong in your else block. First of all,

    $(this).closest('tr').slideToggle();
    

    is going to slide up your parent row, which is not what you want – you want to hide the child row.

     var $detailRow = $(this).closest('tr').next('tr').hasClass('expand-child');
    

    hasClass() will return a boolean, you cannot use it to filter a jQuery collection. What you are trying to do is select the next <tr> that has the class .expand-child, like this:

    var $detailRow = $(this).closest('tr').next('tr.expand-child');
    

    The next line makes absolutely no sense.

    $detailRow.style.visibility.toggle('table-row collapse');
    

    I guess you want to toggle the classes of that row instead:

    $detailRow.toggleClass('table-row collapse');
    

    These changes will make the first showing/hiding work. But then there’s a problem in your if block as well:

    $(".expand-child").slideUp();
    

    This will select all elements with the class .expand-child in the DOM. But you’ll probably want to only select the child row of the current parent row.
    I am, however, not going to debug this whole code for you. I think, I have made some of the main issues clear (see this updated fiddle: https://jsfiddle.net/r7sgL7vy/2/) and you’ll hopefully be able to go on from here yourself.

    One more tipp: For performance, store jQuery collections that you use more than once in variables instead of querying them every time you need them. You already do this with $detailRow for example, and with $this = ... – but it’s not used consequently. Why not select and declare all the needed dom elements at the start of the click event handler and then use them everywhere? Besides the performance factor, it also makes your code much cleaner, easier to understand (for you and for others) and easer to spot any mistakes in your logic.

    Login or Signup to reply.
  2. The main problem is that you attached the ID for collapsing on the wrong element. It should be attached to the tr.expand-child element and not the .expand-child td element.

    I would build the .expand-child row in its entirety only once you have an AJAX response.

    And it’s a good habit to cache elements that you will be re-using.

    Here’s how I would revise your code:

    var $table = $('.js-table');
    
    $table.find('.js-view-parents').on('click', function(e) {
        e.preventDefault();
        // cache elements
        var $btn = $(e.target), $row = $btn.closest('tr'),
            // find next immediate .expand-child
            $nextRow = $row.next('tr.expand-child'); 
        // toggle button
        $btn.toggleClass('glyphicon-eye-close glyphicon-eye-open');
        // if .expand-child row exist already, toggle
        if ($nextRow.length) {
            // show or hide .expand-child row if eye button is open or not, respectively
            $nextRow.toggle($btn.hasClass('glyphicon-eye-open'));
        // if not, create .expand-child row
        } else {
            $.ajax({
                url: '/echo/json/',
                dataType: "json",
                data: parentsData,
                success: function (parentsData) {
                    var newRow = '<tr class="expand-child" id="collapse' + $btn.data('id') + '">' +
                        '<td colspan="12">' +
                        '<table class="table table-condensed table-bordered" width=100% >' +
                        '<thead>' +
                        '<tr>' +
                        '<th>Surname</th>' +
                        '<th>FirstName</th>' +
                        '<th>School Id</th>' +
                        '<th>School name</th>' +
                        '</tr>' +
                        '</thead>' +
                        '<tbody>';
                    if (parentsData.parents) {
                        $.each(parentsData.parents, function(i, parent) {
                            newRow += '<tr>' +
                            '<td>' + parent.Firstname + '</td>' +
                            '<td>' + parent.Surname + '</td>' +
                            '<td>' + parent.schoolId + '</td>' +
                            '<td>' + parent.schoolName + ' ' + parent.commune + '</td>' +
                            '</tr>';
                        });
                    }
                    newRow += '</tbody></table></td></tr>';
                    $row.after(newRow);
                }
            });
        }
    });
    

    Demo

    For demo purposes, I have commented out the AJAX call.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search