mardi 9 juin 2020

Identical checkboxes bound together with jQuery don't sync

I have a dynamically generated form with groups of checkboxes representing categories of companies. These eventually get plotted on a dynamic chart (not shown here). Each group of companies has a toggle button to turn all the checkboxes on or off in each category.

Some companies are in multiple categories. For example, Apple is in both the Tech Giants and Handset Manufacturers category. So I bind identical checkboxes together such that if Apple is checked/unchecked in one category, it will automatically change in any other category it's in. This works well when clicking individual checkboxes, such as Apple's.

However, the checkbox binding doesn't work when a toggle button is clicked that checks or unchecks entire categories of companies.

An example: Click Apple's checkbox in this Fiddle and you'll see it sync in both categories it's in. But when clicking either toggle button, Apple doesn't sync in the other category.

https://jsfiddle.net/105q7d94/1/

Any idea how to fix this?

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<!-- This button is different than the other buttons -->
<button class="button-text" id="customize-button">Open User Settings</button>

<!-- Placeholder for dynamic form -->
<div id="company-selection-form"></div>

<script type="text/javascript">

function toMachineString(humanString) {
  var machineString = humanString.replace(/\s+/g, '-').toLowerCase();
  machineString = machineString.replace('&','');
  return machineString;
}

// Setup the form
var categories = new Map([
  ['Tech Giants',['Alphabet','Amazon','Apple','Facebook','Microsoft']], 
  ['Handset Manufacturers',['Apple','Samsung','Motorola','Sony']]
  //  ... more ...
  ]);

// Build company selection form inputs
let companySelectionHTML = '';

for (let category of categories) {

  categoryName = category[0];
  categoryList = category[1];

  // Setup a div to differentiate each category of companies.
  // Will be used for turning on/off categories en masse
  companySelectionHTML += `<div id="${toMachineString(categoryName)}">\n`;

  // Category heading
  companySelectionHTML += `<h4>${categoryName}</h4><button class="category" id="btn-${toMachineString(categoryName)}" data-checked="true">Toggle</button>`;

  categoryList.forEach(companyName => {

    companySelectionHTML += `
      <label class="checkbox-label">
          <input id="x-${toMachineString(companyName)}" class="checkbox" type="checkbox" name="company" value="${companyName}" checked>
          <label for="x-${toMachineString(companyName)}">${companyName}</label>
      </label>`;
  });

  companySelectionHTML += '</div>\n</div>\n</div>\n';
}

// Append to DOM
const companySelectionId = document.getElementById('company-selection-form');
companySelectionId.insertAdjacentHTML('beforeend', companySelectionHTML);

// Arm the toggle buttons
$(document).ready(function() {
  $(document).on("click", ".category", function() {
    var buttonData = $(this).data();
    $(this).closest("div").find('input[type=checkbox]').prop('checked', !buttonData.checked);
    buttonData.checked = !buttonData.checked;
  });
});

// Bind identical checkboxes
// This works on individual checkboxes but not when clicking the toggle button
$(document).ready(function(){
  $('input:checkbox').on('change', function(){
    $('input[value="' + this.value + '"]:checkbox').prop('checked', this.checked);
    refresh();
  });
});
</script>



Aucun commentaire:

Enregistrer un commentaire