Search code examples
javascriptjquerybootstrap-4event-propagation

How to prevent Bootstrap 4 dropdown to show on input element click?


Following is a simple bootstrap dropdown menu, with the exception that the toggle element is a text input. I don't want the dropdown menu to show on click event, rather, I want to show it on user input, so that I can dynamically populate the menu based on that input.

The click event handler below prevents the dropdown from showing before the user has input anything in the input element, and when there is any input, the input handler shows the dropdown menu. However once the user has input something into the element, and dropdown has shown. Afterwards, the any subsequent click on the input element shows the dropdown menu, and the click handler runs but does not prevent the dropdown from showing even if the user clears all input.

Does Bootstrap attach any new events, or am I not understanding events very well? How could I make this work?

$('#exampleFormControlInput1').on('click', e=>{
  e.preventDefault();
  e.stopPropagation();
  console.log('Dropdown prevented');
});

$('#exampleFormControlInput1').on('input', e=>{
  $('#exampleFormControlInput1').dropdown('show');
});
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-fQybjgWLrvvRgtW6bFlB7jaZrFsaBXjsOMm/tB9LTS58ONXgqbR9W8oWht/amnpF" crossorigin="anonymous"></script>

<div class="container">
  <div class="dropdown">
    <label for="exampleFormControlInput1" class="form-label" id="dropdownMenuButton1">Input with autocomplete</label>
    <input type="text" class="form-control" id="exampleFormControlInput1" placeholder="Search for something" data-toggle="dropdown" aria-expanded="false">
    <ul class="dropdown-menu" aria-labelledby="exampleFormControlInput1">
      <li><a class="dropdown-item" href="#">Action</a></li>
      <li><a class="dropdown-item" href="#">Another action</a></li>
      <li><a class="dropdown-item" href="#">Something else here</a></li>
    </ul>
  </div>
</div>


Solution

  • You don't need to add new click handlers. Use Bootstrap's events and methods instead: https://getbootstrap.com/docs/4.6/components/dropdowns/#methods

    To prevent the dropdown from opening when the input field is empty, block the show.bs.dropdown event. Note that:

    All dropdown events are fired at the .dropdown-menu’s parent element and have a relatedTarget property, whose value is the toggling anchor element.

    To show the list when data appears in the field, and hide when the field becomes empty, you can use the .dropdown() method.

    https://codepen.io/glebkema/pen/RwZMNzE?editors=1011

    $(function() {
    
      // prevent the list from opening by clicking on an empty field
      $(".dropdown").on("show.bs.dropdown", function(e) {
        if (!e.relatedTarget.value) {
          return false;
        }
      });
    
      // handle changes in the input field
      $("#exampleFormControlInput1").on("input", function(e) {
        if (this.value) {
          $(this).dropdown("show");
        } else {
          $(this).dropdown("hide");
        }
      });
    });
    <div class="container">
      <div class="dropdown">
        <label for="exampleFormControlInput1" class="form-label" id="dropdownMenuButton1">Input with autocomplete</label>
        <input type="text" class="form-control" id="exampleFormControlInput1" placeholder="Search for something" data-toggle="dropdown" aria-expanded="false">
        <ul class="dropdown-menu" aria-labelledby="exampleFormControlInput1">
          <li><a class="dropdown-item" href="#">Action</a></li>
          <li><a class="dropdown-item" href="#">Another action</a></li>
          <li><a class="dropdown-item" href="#">Something else here</a></li>
        </ul>
      </div>
    </div>
    
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-fQybjgWLrvvRgtW6bFlB7jaZrFsaBXjsOMm/tB9LTS58ONXgqbR9W8oWht/amnpF" crossorigin="anonymous"></script>