Search code examples
jquerytwitter-bootstraponclickradio-button

jQuery .on() method fails with bootstrap


I have two radio buttons that worked perfectly fine before including bootstrap into my page. I'm not sure why bootstrap would interfere with a simple .on() jQuery method... It is driving me crazy because I've tried various other methods like onClick and it also didn't work.

The bootstrap library I've included:

<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

The jQuery used for testing that worked before including Bootstrap:

$(document).ready(function(){
    $('#button2').on('click', function () {
        alert('it works!');
    });

    $('#button1').on('click', function () {
        alert('it works!');
    });
});

Testing HTML:

<div class='btn-group oneLine' data-toggle='buttons'>
    <label class='btn btn-primary'>
        <input type='radio' name='options' id='button1' autocomplete='off'> <a class='test'>Button 1</a>
    </label>

    <label class='btn btn-primary'>
        <input type='radio' name='options' id='button2' autocomplete='off' checked> <a class='test'>Button 2</a>
    </label>
</div>

I've added the code for live testing below (without bootstrap included):

$(document).ready(function(){
  $('#button2').on('click', function () {
    alert('it works!');
  });

  $('#button1').on('click', function () {
    alert('it works!');
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='btn-group oneLine' data-toggle='buttons'>
  <label class='btn btn-primary'>
    <input type='radio' name='options' id='button1' autocomplete='off'> <a class='test'>Button 1</a>
  </label>

  <label class='btn btn-primary'>
    <input type='radio' name='options' id='button2' autocomplete='off' checked> <a class='test'>Button 2</a>
  </label>
</div>


Solution

  • I'm not sure why bootstrap would interfere with a simple .on() jQuery method...

    That happens because "boostrap" adds the following two styles for each radio input element:

    • clip: rect(0,0,0,0): the clip CSS property defines what portion of an element is visible.

    • pointer-events: none: The CSS property pointer-events allows authors to control under what circumstances (if any) a particular graphic element can become the target of mouse events.

    Now, you have two strategy: remove these two styles or consider another approach.

    Your radio button is contained inside a label. Each click event is captured from the label or anchor and nothing is passed to the radio button.

    This means that the event handler must be attached to the label:

    $('#button2').closest('.btn')
    

    You may reduce the lines of code using Attribute Starts With Selector and querySelector.

    An alternative way is to use directly the label.

    The snippet:

    $(document).ready(function(){
      $('[id^="button"]').closest('.btn').on('click', function () {
        console.log(this.querySelector('input').id + ': it works!');
      });
    
      $('div.btn-group.oneLine label.btn').on('click', function () {
        console.log('An alternative way is to use the label: ' + this.querySelector('input').id + ': it works!');
      });
    
    });
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
    
    <div class='btn-group oneLine' data-toggle='buttons'>
        <label class='btn btn-primary'>
            <input type='radio' name='options' id='button1' autocomplete='off'> <a class='test'>Button 1</a>
        </label>
    
        <label class='btn btn-primary'>
            <input type='radio' name='options' id='button2' autocomplete='off' checked> <a class='test'>Button 2</a>
        </label>
    </div>