6

I have the following setup: 2 checkboxes such that when the first is checked, it toggles the state of the second one. The second one has an onchange listener which is supposed to trigger an alert when it changes.

Problem is, when I click on it, the onchange is fired alright, but when I use the first to change it's state, the event isn't fired.

I'm I missing something? or is the onchange event basically meant to act like an onclick?

<!DOCTYPE html>
<html>
<body>

  <form action="">
    <input id='one' type="checkbox" name="vehicle" value="Bike">I have a bike<br>
    <input id='two' type="checkbox" name="vehicle" value="Car" checked>I have a car 
  </form>
  <script>
    function show(){
      alert(document.getElementById('two').checked);
    }

    document.getElementById('one').addEventListener('click', function(){
      var two = document.getElementById('two');
      two.checked = ! two.checked;
    });

    document.getElementById('two').addEventListener('change', function(){
      alert("changed");
    });
  </script>

</body>
</html>

Thanks for helping :)

SamAko
  • 3,485
  • 7
  • 41
  • 77
  • 2
    I may be wrong, but I don't think that programatically changing a checkbox fires it's change event. – Jesse Kernaghan May 27 '15 at 16:33
  • 2
    You have to fire the event manually. See http://stackoverflow.com/questions/2856513/how-can-i-trigger-an-onchange-event-manually – AmmarCSE May 27 '15 at 16:33
  • My real setup isn't like this, I'm working with a library called switchery that gives stylish checkboxes. The library hides the actual checkbox and creates the styled one. but the actual checkboxes state still updates to reflect that of the styled one. So I want to listen for change events and update angualr scope variables as needed. – SamAko May 27 '15 at 16:35

2 Answers2

8

You are changing an attribute, that will not make the event fire, you can either trigger the change event, or instead click the second checkbox.

Try changing:

document.getElementById('one').addEventListener('click', function(){
  var two = document.getElementById('two');
  two.checked = ! two.checked;
});

To:

document.getElementById('one').addEventListener('click', function(){
  document.getElementById('two').click()
});

Another solution would be triggering the change event:

document.getElementById('one').addEventListener('click', function(){
  var two = document.getElementById('two');
  two.checked = ! two.checked;
  two.dispatchEvent('change');
});
taxicala
  • 21,408
  • 7
  • 37
  • 66
  • 4
    Small correction on the second solution (according to [MDN](https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events)): `two.dispatchEvent(new Event('change'));` – Kevin Farrugia Oct 20 '16 at 09:56
  • https://stackoverflow.com/a/10159237/658035 references a microsoft webpage saying the following "The onchange event does not fire when the selected option of the select object is changed programmatically." I haven't come across a statement like that elsewhere, but it appears to be true in several browsers and was stated at the beginning of this answer. – Jose_X Jun 05 '17 at 10:36
0

If the goal is to have only one checkbox checked, here is a jQuery solution:

$(document).ready(function () {

    $('#one, #two').change(function (e) {
        if ($(this).prop('checked')) {
            $('#one, #two').not(this).prop('checked', false)
        }
    });

});
Ted
  • 14,757
  • 2
  • 41
  • 58