Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

set checkboxes checked based on user input

Tags:

I have these HTML elements:

<div>
    <form>
        <div class="form-group">
            <label class="control-label"></label>
            <input type="text" value="1100" class="myCars">
        </div>
    </form>
    <form>
        <div class="form-group">
            <label class="control-label"></label>
            <input type="text" value="0011" class="myCars">
        </div>
    </form>
</div>

Here are my checkboxes:

var elem = $('.myCars');
var car = ['car1', 'car2', "car3", "car4"];
var container = '<ul class="cars">';

for (i = 0; i < car.length; i++) {
    container += '<li>' +
        '<label class="container ' + car[i] + '">' +
        '<input type="checkbox">' +
        '<span class="checkmark"></span>' +
        '</label>' +
        '</li>';

}
container += '</ul>'
elem.closest('div').append(container);

After configuring the checkboxes I want to go through all inputs and set checkboxes as checked where input values are 1

I have tried this:

$('.myCars').each(function() {
    var arr = $(this).val()
    var array = arr.split('')
    // array values: 
    Array(4)["1", "1", "0", "0"]
    Array(4)["0", "0", "1", "1"]

    $('.myCars').prop('checked', function(index) {
        return +array[index] === 1;
    });
})

How can I make it work?

like image 902
tery Avatar asked Nov 02 '18 08:11

tery


People also ask

How do I make a checkbox automatically checked in HTML?

You can code a checkbox to be pre-selected when the page loads using the checked boolean attribute. You simply have to add the word checked within the opening tag of the input element. Here's an example of a checkbox toggled on by default: HTML.

Can we assign value to checkbox?

The value property sets or returns the value of the value attribute of a checkbox. For checkboxes, the contents of the value property do not appear in the user interface. The value property only has meaning when submitting a form.


2 Answers

One possible answer to your question is:

// select the .myCars elements, and bind the anonymous function
// of the on() method as the event-handler for the 'input'
// event:
$('.myCars').on('input', function() {

  // retrieve the entered value, and then use String.prototype.trim()
  // to remove leading/trailing white-space:
  let enteredValue = $(this).val().trim(),

    // convert that String into an Array, using
    // String.prototype.split('') (as in your own posted code), then
    // use Array.prototype.map() to iterate over every Array value
    // with a call to the Number() function to convert the entered
    // values to Numbers:
    valueArray = enteredValue.split('').map(Number);

  // navigate to the closest ancestor <div> element:
  $(this).closest('div')
    // find the <input type="checkbox"> elements:
    .find('input[type=checkbox]')
    // update the 'checked' property using the anonymous function,
    // here we pass in the index of the current element:
    .prop('checked', function(index) {
      // we return the assessment of whether the array-value at
      // the current index is exactly equal to 1 (if true this
      // checks the check-box, if false it unchecks the box, or
      // leaves it unchecked); this is why we used the call to
      // Array.prototype.map(Number) earlier:
      return valueArray[index] === 1;
  });

// triggering the 'input' event so the checkboxes are updated
// on page load:
}).trigger('input');

var elem = $('.myCars');

var car = ['car1', 'car2', "car3", "car4"];
var container = '<ul class="cars">';

for (i = 0; i < car.length; i++) {
  container += '<li>' +
    '<label class="container ' + car[i] + '">' +
    '<input type="checkbox">' +
    '<span class="checkmark"></span>' +
    '</label>' +
    '</li>';

}
container += '</ul>'
elem.closest('div').append(container);

$('.myCars').on('input', function() {
  let enteredValue = $(this).val().trim(),
    valueArray = enteredValue.split('').map(Number);
  $(this).closest('div').find('input[type=checkbox]').prop('checked', function(index) {
    return valueArray[index] === 1;
  });
}).trigger('input');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
  <form>
    <div class="form-group">
      <label class="control-label"></label>
      <input type="text" value="1010" class="myCars">
    </div>
  </form>
  <form>
    <div class="form-group">
      <label class="control-label"></label>
      <input type="text" value="0011" class="myCars">
    </div>
  </form>
</div>

JS Fiddle demo.

An alternative to the above is the following, using just the plain DOM API. Note that in this approach I've made use of a <template> element, rather than creating a string of HTML and also wrapped the entirety of your <form> elements in one <form>:

// using let, rather than var, as personal preference in this
// case; using document.querySelectorAll() to retrieve a
// non-live NodeList of the elements matching the supplied
// CSS selector:
let elems = document.querySelectorAll('.myCars'),
  car = ['car1', 'car2', "car3", "car4"],

  // using `document.createElement()` to create the <ul>:
  container = document.createElement('ul');

// retrieving the content of the <template> element, accessed
// via its id (using a CSS selector), and the content property:
template = document.querySelector('#carCheckboxes').content,

  // creating an InputEvent:
  inputEvent = new Event('input'),

  // defining the function to handle updates to the checkboxes,
  // passing in the Event Object (here referred to as 'e'):
  updateCheckmarks = (e) => {

    // e.currentTarget is the element to which the event-listener
    // is bound:
    let source = e.currentTarget,

      // here we retrieve the value of the current element,
      // use String.prototype.trim() to remove the leading/
      // trailing white-space, use String.prototype.split('')
      // to convert the String to an Array of characters, and
      // and finally a call to Array.prototype.map(Number)
      // (as above) to convert the array-entries into numbers:
      value = source.value.trim().split('').map(Number),

      // here we find the check-boxes, navigating to the
      // closest ancestor <div>:
      checkmarks = source.closest('div')
        // and finding the <input type="checkbox"> elements within:
        .querySelectorAll('input[type=checkbox]');

    // using Array.prototype.forEach() to iterate over that Array;
    // check: the (user defined name for) the current <input> element,
    // index: the (user defined name for) the index of the current
    // <input> in the Array over which we're iterating:
    checkmarks.forEach(function(check, index) {

      // here we set the checked property to true/false,
      // depending on the following assessment:
      check.checked = value[index] === 1;
    });
  };

// iterating over the car Array, using Array.prototype.forEach():
car.forEach(function(el) {

  // cloning the content template, including descendant elements
  // using Node.cloneNode(true):
  let model = template.cloneNode(true);

  // appending that cloned node to the container:
  container.appendChild(model);
})

// iterating over the elems Array:
elems.forEach(
  // using an Arrow function; 'el' is the (user defined name
  // for) the current element of the Array of elements:
  (el) => {

    // appending a cloned container Node to the closest
    // ancestor <div> element:
    el.closest('div').appendChild(container.cloneNode(true));

    // binding the updateCheckmarks() function as the
    // event-handler for the 'input' event:
    el.addEventListener('input', updateCheckmarks);

    // firing the inputEvent (created earlier) on the
    // the current element, in order to trigger the
    // function on page-load:
    el.dispatchEvent(inputEvent);
  });

let elems = document.querySelectorAll('.myCars'),
  car = ['car1', 'car2', "car3", "car4"],
  container = document.createElement('ul');
template = document.querySelector('#carCheckboxes').content,
  inputEvent = new Event('input'),
  updateCheckmarks = (e) => {
    let source = e.currentTarget,
      value = source.value.trim().split('').map(Number),
      checkmarks = source.closest('div').querySelectorAll('input[type=checkbox]');
    checkmarks.forEach(function(check, index) {
      check.checked = value[index] === 1;
    });
  };

car.forEach(function(el) {
  let model = template.cloneNode(true);
  container.appendChild(model);
})

elems.forEach(
  (el) => {
    el.closest('div').appendChild(container.cloneNode(true));
    el.addEventListener('input', updateCheckmarks);
    el.dispatchEvent(inputEvent);
  });
<template id="carCheckboxes">
  <li>
  <label>
    <input type="checkbox"><span class="checkmark"></span>
  </label>
  </li>
</template>
<div>
  <form>
    <div class="form-group">
      <label class="control-label"></label>
      <input type="text" value="1010" class="myCars">
    </div>
    <div class="form-group">
      <label class="control-label"></label>
      <input type="text" value="0011" class="myCars">
    </div>
  </form>
</div>

With regards to your question, in comments, to another answer:

[How] can [I] use onClick to change each checkbox value? [Because] when [I] do that the values of checkboxes in all inputs are changing.

This is possible using:

// while this code - in my example - runs after the <input>
// elements are created, and appended to the DOM, we're
// binding the event-handler, using the on() method, to
// already-existing elements; so here we select the <form>
// element, and bind the anonymous function of the on()
// method as the 'change' event-handler:
$('form').on('change', function(e) {

  // caching variables:
  let form = $(this),
      valuesInput = form.find('.myCars'),

      // finding the <input type="checkbox"> elements within
      // the <form> element:
      checkboxValues = form.find('input[type=checkbox]')

        // using map() - the jQuery method - to iterate over
        // the collection to form an Array-like Object:
        .map(function(index, el) {

          // here we return 1 (if the current element is checked),
          // or 0 if it is not checked:
          return el.checked ? 1 : 0;
    // using the get() method to convert the Array-like Object
    // into an Array:
    }).get()
    // using join() to convert that array into a String, passing
    // in an empty string ('') to act as the joining characters
    // (if no argument is passed the default is a comma):
    .join('');

  // updating the value of the <input class="myCars"> element:
  valuesInput.val(checkboxValues);

// firing the 'change' event on page-load so that the value of
// the text-input reflects the checked/unchecked state of the
// checkboxes:
}).trigger('change');

let elem = $('.myCars'),
    car = ['car1', 'car2', "car3", "car4"],
   container = '<ul class="cars">';

for (i = 0; i < car.length; i++) {
  container += '<li>' +
    '<label class="container ' + car[i] + '">' +
    '<input type="checkbox">' +
    '<span class="checkmark"></span>' +
    '</label>' +
    '</li>';

}
container += '</ul>'
elem.closest('div').append(container);

$('.myCars').on('input', function() {
  let enteredValue = $(this).val().trim(),
      valueArray = enteredValue.split('').map(Number);
  $(this).closest('div').find('input[type=checkbox]').prop('checked', function(index) {
    return valueArray[index] === 1;
  });
}).trigger('input');

$('form').on('change', function(e) {
  let form = $(this),
      valuesInput = form.find('.myCars'),
      checkboxValues = form.find('input[type=checkbox]').map(function(index, el) {
        return el.checked ? 1 : 0;
    }).get().join();
    
  valuesInput.val(checkboxValues);
}).trigger('change');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
  <form>
    <div class="form-group">
      <label class="control-label"></label>
      <input type="text" value="" class="myCars">
    </div>
  </form>
  <form>
    <div class="form-group">
      <label class="control-label"></label>
      <input type="text" value="0011" class="myCars">
    </div>
  </form>
</div>

References:

  • CSS:
    • Attribute-selectors.
  • JavaScript:
    • Array.prototype.forEach().
    • Array.prototype.join().
    • Array.prototype.map().
    • HTMLTemplateElement.
    • HTMLTemplateElement.content.
    • Node.cloneNode().
    • Number().
    • String.prototype.split().
    • String.prototype.trim().
  • HTML:
    • <template>.
  • jQuery:
    • closest().
    • find().
    • get().
    • map().
    • on().
    • prop().
    • trigger().
    • val().
like image 161
David Thomas Avatar answered Oct 20 '22 18:10

David Thomas


You could it this way, I followed your logic and didn't change the basic code :

var car = ['car1', 'car2', "car3", "car4"];

$('.myCars').each(function() {
  var arr = $(this).val()
  var array = arr.split('')
  var container = '<ul class="cars">';

  for (i = 0; i < car.length; i++) {
    var checked = array[i] == 1 ? 'checked' : ''
    container += '<li>' +
      '<label class="container ' + car[i] + '">' +
      '<input type="checkbox"' + checked + ' >' +
      '<span class="checkmark"></span>' +
      '</label>' +
      '</li>';

  }
  container += '</ul>'
  $(this).closest('div').append(container);
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js"></script>
<div>
  <form>
    <div class="form-group">
      <label class="control-label"></label>
      <input type="text" value="1100" class="myCars">
    </div>
  </form>
  <form>
    <div class="form-group">
      <label class="control-label"></label>
      <input type="text" value="0011" class="myCars">
    </div>
  </form>
</div>

Basically while going through each input, you create the container while putting checked on each field having 1, as your seem to have wanted the logic to be around that :-)

like image 23
Alexandre Elshobokshy Avatar answered Oct 20 '22 19:10

Alexandre Elshobokshy