0

I have a javascript function that inserts an input of type checkbox next to each button. When the the first checkbox is clicked, its respective button is disabled, and the checkbox remains so when the page is refreshed, in the same way when the checkbox is clicked again the button is re-enabled and remains after page refresh.

My goal is that when the checkbox related to a button is clicked, only that button is disabled. What is happening is that only the first checkbox is triggering the function, and when it is triggered the other checkboxes are also. When I try to click on the second or third checkbox this function doesn't work.

I assume it's because of forEach(). What I need is to make this function work individually for each button and that keeps the checkbox enabled / disabled after page refresh.

<div id="accordion">
  <% turmas.forEach((turma)=> { %>
    <div class="card">
      <div class="card-header" id="headingThree>">
        <h5 class="mb-0 d-flex">
          <div id="billing">
            <input type="checkbox" id="billing-checkbox" checked>
            <button class="btn btn-info text-white collapsed d-flex align-center" data-toggle="collapse" data-target="#<%= turma.nome %>" aria-expanded="false" aria-controls="<%= turma.nome %>" id="btn">
              <%= turma.nome %>
            </button>
          </div>
        </h5>
      </div>
    </div>
  <% }) %>
$(document).ready(function() {
  $('#billing-checkbox').prop('checked', localStorage.getItem('buttonDisabled') !== "disabled");
  toggleBilling({
    target: $('#billing-checkbox')[0]
  })
  $('#billing-checkbox').on('change', toggleBilling);
});

function toggleBilling(e) {
  $('#billing button').attr('disabled', !e.target.checked)
  localStorage.setItem('buttonDisabled', $('#billing button').attr('disabled'));
}

Update 24/06/21:

The user @RoryMcCrossan created a solution that makes each checkbox work individually for each button, but there is a problem, when the button is disabled, when trying to reactivate it, it does not enable it again on Google Chrome.

jQuery($ => {
  $('.billing-checkbox').on('change', e => {
    $(e.target).next('button').prop('disabled', !e.checked);
  });
});

JSFiddle

And here is the code that allows the checkbox to remain enabled/disabled after refreshing the page

$(document).ready(function() {
    $('.billing-checkbox').prop('checked', localStorage.getItem('buttonDisabled') !== "disabled");
    toggleBilling({
        target: $('.billing-checkbox')[0]
  })
  $('.billing-checkbox').on('change', toggleBilling);
});

function toggleBilling(e) {
    $('.billing input[type="button"]').attr('disabled', !e.target.checked)
    localStorage.setItem('buttonDisabled', $('.billing input[type="button"]').attr('disabled'));
}

JSFiddle

The ideal would be to join both functions, but I've been trying without success.

M. Bran
  • 21
  • 5

2 Answers2

2

The main issue is because you're repeating the same id on multiple elements as the loop builds the HTML. To correct this remove the id attributes and use class instead.

From there you can update your jQuery code to use DOM traversal to find the button element related to the changed checkbox. In this specific case, by using the next() method:

jQuery($ => {
  $('.billing-checkbox').on('change', e => {
    $(e.target).next('button').prop('disabled', !e.checked);
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css" />
<div id="accordion">
  <!-- repeated content \/ -->
  <div class="card">
    <div class="card-header headingThree">
      <h5 class="mb-0 d-flex">
        <div class="billing">
          <input type="checkbox" class="billing-checkbox" />
          <button class="btn btn-info text-white collapsed d-flex align-center" data-toggle="collapse" data-target="#<%= turma.nome %>" aria-expanded="false" aria-controls="turma.nome" id="btn">
            turma.nome
          </button>
        </div>
      </h5>
    </div>
  </div>
  <!-- repeated content /\ -->

  <div class="card">
    <div class="card-header headingThree">
      <h5 class="mb-0 d-flex">
        <div class="billing">
          <input type="checkbox" class="billing-checkbox" />
          <button class="btn btn-info text-white collapsed d-flex align-center" data-toggle="collapse" data-target="#<%= turma.nome %>" aria-expanded="false" aria-controls="turma.nome" id="btn">
            turma.nome
          </button>
        </div>
      </h5>
    </div>
  </div>

  <div class="card">
    <div class="card-header headingThree">
      <h5 class="mb-0 d-flex">
        <div class="billing">
          <input type="checkbox" class="billing-checkbox" />
          <button class="btn btn-info text-white collapsed d-flex align-center" data-toggle="collapse" data-target="#<%= turma.nome %>" aria-expanded="false" aria-controls="turma.nome" id="btn">
            turma.nome
          </button>
        </div>
      </h5>
    </div>
  </div>
  <div class="card">
    <div class="card-header headingThree">
      <h5 class="mb-0 d-flex">
        <div class="billing">
          <input type="checkbox" class="billing-checkbox" />
          <button class="btn btn-info text-white collapsed d-flex align-center" data-toggle="collapse" data-target="#<%= turma.nome %>" aria-expanded="false" aria-controls="turma.nome" id="btn">
            turma.nome
          </button>
        </div>
      </h5>
    </div>
  </div>
</div>

-- Update --

Given your comment below about needing to also save the state of the multiple checkbox/button combinations in localStorage, you can achieve that by building an array from the state of the checkboxes and storing that. Here's a jsFiddle demonstrating that (as SO snippets are sandboxed and can't access localStorage)

jsFiddle

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
  • This partly solved my problem. Now he is selecting and disabling the buttons individually and I appreciate that, but the function that was there before was used to "memorize" the behavior of the checkbox, if disabled it would remain so when reloading the page, if enabled the same thing. I tested it on google chrome and when I disable the button through the checkbox, when I click it again to reactivate the button, it also stopped working. – M. Bran Jun 24 '21 at 20:33
  • I updated the answer to show you how to do that – Rory McCrossan Jun 25 '21 at 08:52
-1

Remove button use label instead and make label look like button using css. Add for attribute in label same as id in button, but remember to make every id different, easy way to do it is to concatenate with array index or id of element like this:

<label for="#<%= turma.id %><%= turma.nome %>"></label>
<input id="<%= turma.id %><%= turma.nome %>" value="<%= turma.nome %>">

Please provide your comment if you are facing a problem again. thanks

iftikharyk
  • 870
  • 5
  • 10