How get each element of an Array? [closed]

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.

Answer

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/[email protected]/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