1

I have a form that presents as a DataTable with checkmarks on each row. The user should be able to check up to 10 checkboxes. Once the tenth is checked, all the unchecked checkboxes need to be disabled until the user unchecks at least one to go back below the limit. Everything works fine, except when I start playing with the number of rows per page. If I go from 25 to 10 rows and then go back and forth through different pages, some checkboxes are still disabled while others are not. The total count of checked checkboxes is always right though. I'm not sure how to refresh the 'disabled' attribute when the table is redrawn.

This is the HTML code:

<div class="card-header pb-0 card-no-border">
    <span>Select up to 10 playlists for this song. You can select up to 10 playlists daily.</span>
</div>
<div class="alert alert-warning inverse alert-dismissible fade show" role="alert"
    id="pageMessages">
    <i class="icon-info-alt"></i>
    <p id="limitCounter">0 playlists selected from limit of 10</p>
</div>

<div class="card-body">
    <div class="table-responsive HideScrollbar">
        <form method="POST" action="submission_agreement.php">
            <table class="display" id="basic-1" data-page-length="25">
                <thead>
                    <tr>
                    <th class="no-sort">Cover</th>
                    <th>Details</th>
                    <th>Saves</th>
                    <th>Songs</th>
                    <th>Updated</th>
                    <th class="no-sort">Select</th>
                    </tr>
                </thead>
                <tbody>
                    <tr>
                        <td><img src="assets/images/playlists/playlist-cover-1.png" alt=""></td>
                        <td>
                        <h6>Contemporary Piano</h6>
                        <span>
                            by <a href="#">antonioromopiano</a><br>
                            Submissions: 1,013 | Approval rate: 43%<br>
                            neo-classical · instrumental · cinematic · calming
                        </span>
                        </td>
                        <td>539 <i class="fa fa-heart-o fa-sm"></i></td>
                        <td>150 <i class="fa fa-music"></i></td>
                        <td class="font-success">2023 05 27</td>
                        <td>
                            <input type="checkbox" id="checkpoint1" class="checkpoint ms-4" name="checkpoints"
                            value="{{playlist.id}}">
                        </td>
                    </tr>
                    <tr>
                        ... many rows like the one above ...
                    </tr>
                </tbody>
            </table>
            <div class="col text-center mt-3">
                <button class="btn btn-primary btn-next" type="submit" id="done_selecting">Done Selecting Playlists</button>
            </div>
        </form>
    </div>
</div>

And this is my JavaScript:

<script>

  $(document).ready(function () {
    $("input[id^='checkpoint']").change(function () {
      const checkbox_limit = 10;
      const checkboxes = document.querySelectorAll('input[type="checkbox"]');

      var element = document.getElementById("pageMessages");
      var $table = $('#basic-1').dataTable();
      var allNodes = $table.fnGetNodes();
      var total_checked = 0;

      $(allNodes).each(function () {
        $(this).change(updatetotal_checked);
      });
    
      updatetotal_checked();

      function updatetotal_checked () {
    
        total_checked = $(allNodes).find("input[name='checkpoints']:checked").length;
  
        $("#total_checked").text(total_checked);
        if (total_checked > 0) {         
          $("#status").toggle(total_checked > 0);
        }
          
      };

      /* Disable unchecked checkboxes if total checked = 10 */
      checkboxes.forEach((checkbox) => {
        checkbox.disabled = total_checked >= checkbox_limit && !checkbox.checked;
      });

      /* Disable submit button if at least one playlist hasn't been selected */
      if (total_checked == 0) {
        document.getElementById('done_selecting').setAttribute('disabled', '');
      }
      else {
        document.getElementById('done_selecting').removeAttribute('disabled');
      }

      /* Change alert color if total checked = 10 */
      if (total_checked >= checkbox_limit) {
        element.classList.remove("alert-warning");
        element.classList.add("alert-danger");
      } else {
        element.classList.remove("alert-danger");
        element.classList.add("alert-warning");
      }

      /* Update alert text with total checked */
      const limitCounter = document.getElementById('limitCounter');
      limitCounter.textContent = `${total_checked} playlists selected from limit of ${checkbox_limit}`;      

    });

    /* To set initial state */
    $("input[id^='checkpoint']").trigger('change');

  });

</script>

Any help is greatly appreciated!

3
  • Where is your data coming from? Is this in a CMS or framework of some kind? Correct me if I'm misunderstanding, but it seems you're having an issue when the table is "redrawn" but I don't see anything in your provided html / js which would indicate the table being "redrawn". Are you navigating to another page and wanting the checkboxes to remain consistent between pages? Commented Feb 25 at 20:34
  • @asyncawait it's jQuery datatables, and the table is being instantiated here: var $table = $('#basic-1').dataTable();. However, you're correct in that I also don't see where $table is being redrawn in the datatables sense of the word (we would see draw() being called). Moreover, there shouldn't be a need to call draw() because rows aren't being added / deleted. I suspect "redraw" may refer to what datatables natively does when the user changing the number of rows shown per page. Commented Feb 25 at 20:56
  • Right now, I'm testing everything with sample static data. And yes, @devlin, I'm using jQuery DataTables. By 'redraw' I'm referring to the pagination that DataTables offers natively, just like Devlin said. When you click on a page number, the table rows are refreshed and that's where I'm having the issue. Some of the checkmarks presented when going to a different page may be disabled when they aren't supposed to be or the opposite happens as well. Commented Feb 25 at 21:04

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.