51

I have a bootstrap dropdown menu below. It has a link in it hooked up to a knockout.js binding, that returns false because I don't want the # tag to be sent to the browser URL. However, doing this doesn't close the dropdown menu when I click the link. Any way around this?

HTML

<div class="btn-group">
    <button class="btn dropdown-toggle" data-toggle="dropdown" data-bind="enable: !noResults()"><i class="icon-download-alt" ></i> Export <span class="icon-caret-down"></span></button>

    <ul class="dropdown-menu">
        @foreach(var exportUrl in Model.ExportUrls)
        {
            <li>
                <a href="#" data-bind="disable: noResults(), download: { url: '@exportUrl.Value', data: data }"><img src="/Content/less/images/img/@(exportUrl.Key.ToString().ToLower()).png" alt="@exportUrl.Key.GetDisplayName()"/> @exportUrl.Key.GetDisplayName()</a>
            </li>
        }
    </ul>
</div>

knockut.js binding

ko.bindingHandlers.download = {
    init: function (element, valueAccessor) {

        var value = ko.utils.unwrapObservable(valueAccessor()),
            id = 'download-iframe-container',
            iframe;

        $(element).unbind('click').bind('click', function () {

            iframe = document.getElementById(id);

            if (!iframe) {
                iframe = document.createElement("iframe");
                iframe.id = id;
                iframe.style.display = "none";
            }

            if (value.data) {
                iframe.src = value.url + (value.url.indexOf('?') > 0 ? '&' : '?') + $.param(ko.mapping.toJS(value.data));
            } else {
                iframe.src = value.url;
            }

            document.body.appendChild(iframe);

            return false;
        });
    }
};
Null
  • 1,950
  • 9
  • 30
  • 33
Mike Flynn
  • 22,342
  • 54
  • 182
  • 341

13 Answers13

59

Give your links a class (e.g. download):

<a href="#" class="download" data-bind="disable: noResults()....

And your dropdown an id (e.g. dlDropDown):

<button class="btn dropdown-toggle" id="dlDropDown" data-toggle="dropdown" data-bind="enable: !noResults()">

And then add the following event handler:

$("a.download").click(function() {
   $("#dlDropDown").dropdown("toggle");
});
mccannf
  • 16,619
  • 3
  • 51
  • 63
42

This will actually work with your existing bootstrap markup without having to add any new classes or ids. Hopefully this is helpful to someone else just looking to drop a solution in without changing anything existing.

$(".dropdown-menu a").click(function() {
    $(this).closest(".dropdown-menu").prev().dropdown("toggle");
});
brianespinosa
  • 2,408
  • 12
  • 22
21

This can be achieved with bootstraps own CSS class dropdown-toggle

Just add that class to your link elements like so: <a class='dropdown-toggle'></a> and it will toggle the dropdown.

nullwriter
  • 785
  • 9
  • 34
13

I think this will close all dropdowns and expanded navmenus on the page:

$('.in,.open').removeClass('in open');
Tom
  • 42,844
  • 35
  • 95
  • 101
  • Best answer so far. Some of the other answers prevent the menu from being opened again until the page is reloaded; this does not. My usage: ```$(".modal").on("show.bs.modal", function() { $(".dropdown.in,.dropdown.open").removeClass("in open"); });``` – Derreck Dean Feb 13 '18 at 21:12
  • I aslo found that the class='dropdown-toggle' solution changed the formatting of the dropdown options. This is the best solution for me. – shaw2thefloor Feb 27 '18 at 14:09
9

I unfortunately had no success using .dropdown('toggle') as suggested above...

What did work however was applying bootstrap's dropdown button data attributes to it's own dropdown links:

<button type="button" data-toggle="collapse" data-target=".navbar-collapse" class="navbar-toggle navbar-btn">

...

<ul class="nav navbar-nav">
  <li><a href="#about" class="scroll-to" data-toggle="collapse" data-target=".navbar-collapse">About</a></li>

All I did was add the data-toggle="collapse" and data-target=".navbar-collapse" to each dropdown nav link.

No additional css or js and it worked like a charm :)

Jesse Novotny
  • 704
  • 7
  • 16
5

Using event.preventDefault() instead of return false does the trick.

Change your code to:

$(element).unbind('click').bind('click', function(e) {
  e.preventDefault();

  // ...

  return true; // or just remove the return clause
});
Fábio Batista
  • 25,002
  • 3
  • 56
  • 68
4

Simply change the href="#" to href="javscript:void(0);" and then return true in your click event (instead of false).

iikkoo
  • 2,810
  • 6
  • 33
  • 38
Rich
  • 49
  • 1
  • 1
1

If you've got an event parameter just do:

$(element).unbind('click').bind('click', function (event)
{
    event.preventDefault();
    return true;
});
Dave
  • 11
  • 1
1

A cleaner solution, to keep the dropdown functionality and get what you are looking for.

$("body").on('click', function (e) {
     if (!$(e.target).hasClass("open") && $(e.target).parents(".btn-group.open").length == 0)
         $(this).find(".btn-group.open a").trigger("click");
});
0

the best answer will be is to perform click so it will act the same as the user click the mouse to hide the drop-down menu, to do this add this snap code to your page:

<script>
    $(document).ready(function () {
        $("li.dropdown ul.dropdown-menu li").click(function (event) {
            event.toElement.parentElement.click();
        })
    })
</script>
0

you can also add a transparent mask to block any other unwanted click when dropdown is open:

   OnDomReadyHeaderItem.forScript("$('.dropdown').on('shown.bs.dropdown', function (e) { $(this).append('<span id=\"transparent-mask\"></span>')})"));

   OnDomReadyHeaderItem.forScript("$('.dropdown').on('hidden.bs.dropdown', function (e) { $('#transparent-mask').remove()})"));

with the mask:

.dropdown.open #transparent-mask{
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    display: block;
    margin: auto;
    height: initial;
    z-index: 1000 !important;
}
daniel gi
  • 396
  • 1
  • 7
  • 19
0

when click on menu then the nav will be close this is the easy way to do it using jquery onclick="$('#mobile-menu').removeClass('mm-menu_opened');"

abubakkar tahir
  • 737
  • 1
  • 11
  • 13
0

I have a late answer which might be helpful to someone. Answer posted on 2023, with bootstrap-5 in my machine. Assuming that you have a dropdown button and dropdown menu,

To close the menu after click,

<a href="#" class="dropdown-toggle" data-bs-auto-close="true">

To keep the menu,

<a href="#" class="dropdown-toggle" data-bs-auto-close="outside">
Henshal B
  • 1,540
  • 12
  • 13