0

I have an unordered list with div and a hidden checkbox list, each with the same number of items.

How can I check an item in list 2 when I click a div in list 1 with the same index?

$(document).on('click', '.product-list li', function() {
  var index = $(this).index();
  if ($('.product-checkbox #checkbox index').prop('checked')) {
    $('.product-checkbox #checkbox index').prop('checked', false);
  } else {
    $('.product-checkbox #checkbox index').prop('checked', true);
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js">
</script>
<ul class="product-list">
  <li>
    <div>Red</div>
  </li>
  <li>
    <div>White</div>
  </li>
  <li>
    <div>Blue</div>
  </li>
</ul>

<ul class="product-checkbox">
  <li>
    <input type="checkbox">Red
  </li>
  <li>
    <input type="checkbox">White
  </li>
  <li>
    <input type="checkbox">Blue
  </li>
</ul>

So here if I click Red in the first UL, Red gets checked in the second UL.

I can get the index of the LI in the first but not apply that index to check the box.

ℛɑƒæĿᴿᴹᴿ
  • 4,983
  • 4
  • 38
  • 58
Junky
  • 958
  • 7
  • 17
  • Accessibility-wise you should always use a [Label Element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label) - (And why a UL list at all?) – Roko C. Buljan Feb 07 '22 at 16:06
  • The code for the UL is generated from a script beyond my control. – Junky Feb 07 '22 at 16:08
  • Does this answer your question? [Get an element by index in jQuery](https://stackoverflow.com/questions/9887534/get-an-element-by-index-in-jquery) – Heretic Monkey Feb 07 '22 at 16:13

1 Answers1

2

There's a couple of issues in your logic. Firstly, you can use eq() to select an element within a collection by its index. Secondly, #checkbox is looking for a single element with that id attribute. You should use the :checkbox selector instead to find any element of that type within the parent. Finally, you can make the prop() logic more succinct by providing a function which accepts the current state of the property as an argument and returns the inverted boolean value. Try this:

$(document).on('click', '.product-list li', e => {
  var index = $(e.currentTarget).index();      
  $('.product-checkbox :checkbox').eq(index).prop('checked', (i, checked) => !checked);
});

/* anonymous function version for legacy support:

$(document).on('click', '.product-list li', function() {
  var index = $(this).index();      
  $('.product-checkbox :checkbox').eq(index).prop('checked', function(i, checked) {
    return !checked;
  });
});
*/
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<ul class="product-list">
  <li><div>Red</div></li>
  <li><div>White</div></li>
  <li><div>Blue</div></li>
</ul>

<ul class="product-checkbox">
  <li><input type="checkbox">Red</li>
  <li><input type="checkbox">White</li>
  <li><input type="checkbox">Blue</li>
</ul>

It's also worth noting that what you're doing here can be achieved in HTML alone with no need for JS or jQuery:

<ul class="product-list">
  <li>
    <label>
      Red
      <input type="checkbox" value="Red" />
    </label>
  </li>
  <li>
    <label>
      White
      <input type="checkbox" value="White" />
    </label>
  </li>
  <li>
    <label>
      Blue
      <input type="checkbox" value="Blue" />
    </label>
  </li>
</ul>

Of course, I left the checkboxes visible in both examples so you can see the effect working, but they can still be easily hidden using CSS if necessary.

Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
  • I can't compile arrow functions. Can you please show the code without the arrow function? – Junky Feb 07 '22 at 16:08
  • 1
    Sure - I updated the answer with an example for you – Rory McCrossan Feb 07 '22 at 16:11
  • There have been many questions about getting elements by index before... – Heretic Monkey Feb 07 '22 at 16:14
  • I looked at many questions on SO but the ones I came across did not fit my use pattern and many were up to 10 years old. – Junky Feb 07 '22 at 16:16
  • By just going blindly for `$('.product-checkbox :checkbox')` can give you false positives - as soon as you'll have more than one of suck Elements on your page. It will target the first one in the DOM - instead of the desired one. – Roko C. Buljan Feb 07 '22 at 16:16
  • That's my bad. I tried simplifying the actual code by changing some classes to simpler terms. – Junky Feb 07 '22 at 16:19