6

For some strange reason the bootstrap menu dropdown is not expanded on click when it is constructed through router template. Being used directly in the template it works fine.

Here is the plunker to play with: http://plnkr.co/edit/GOky2ajHl46VddQRKDye?p=preview

<!DOCTYPE html>
<html ng-app="app">
    <head>
        <title>TEST</title>
        <script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
        <link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap.min.css">
        <link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.0.2/css/bootstrap-theme.min.css">
        <script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.2/js/bootstrap.min.js"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular-route.min.js"></script>
        <script>
var app = angular.module('app', [ 'ngRoute', 'ctrls' ]);

app.config(function ($routeProvider) {
    $routeProvider.when('/menu', {
        template : '<menu></menu>',
        controller : 'mainCtrl'
    }).otherwise({ redirectTo: '/menu' });
});

app.directive('menu', function () {
    return {
        restrict : 'E',
        template : '<nav class="navbar navbar-default" role="navigation">' +
          '<ul class="nav navbar-nav">' +
          '  <li class="dropdown">' +
          '    <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>' +
          '    <ul class="dropdown-menu"><li><a href="#">Action</a></li></ul>' +
          '  </li>' +
          '</ul>' +
          '</div>' +
          '</nav>'
    };
});

angular.module('ctrls', [ ]).controller('mainCtrl', function () { });
        </script>
    </head>

    <!-- this menu does not work -->
    <body ng-view></body>

    <!-- this menu works fine: -->
    <!-- <body><menu></menu></body> -->
</html>
Alex Netkachov
  • 13,172
  • 6
  • 53
  • 85
  • Just a guess, but i suspect that the bootstrap js just gets applied once on load and the directive is only attached afterwards. If you mix bootstrap with angular, i would recommend you to use to use ui-bootstrap: http://angular-ui.github.io/bootstrap/ its not ready yet for bootstrap 3, but in most of the cases you're fine, if you adjust the templates it provides. – hugo der hungrige Nov 13 '13 at 23:30
  • Dropdown.prototype.toggle runs when the link is clicked both times - so the events are attached correctly – Alex Netkachov Nov 13 '13 at 23:35
  • Can you provide a fiddle or plunker? – hugo der hungrige Nov 13 '13 at 23:36
  • Here it is: http://plnkr.co/edit/GOky2ajHl46VddQRKDye?p=preview – Alex Netkachov Nov 13 '13 at 23:41

1 Answers1

7

Its actually the '#' of the href attribute of the dropdown-toggle-link which triggers a route change. If you remove href it works: http://plnkr.co/edit/aDLuAk0mBLO6R1LR6ASb?p=preview

But as I said: I wouldn't recommend combining angular and bootstrap in this fashion. UI- bootstrap is usually the better choice when mixing their functionality.

app.directive('menu', function () {
    return {
        restrict : 'E',
        template : '<nav class="navbar navbar-default" role="navigation">' +
          '<ul class="nav navbar-nav">' +
          '  <li class="dropdown">' +

          // remove href = '#' here
          '    <a href class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a>' +

          // probably not the worst idea to remove it here either, if not used otherwise
          '    <ul class="dropdown-menu"><li><a href="#">Action</a></li></ul>' +
          '  </li>' +
          '</ul>' +
          '</div>' +
          '</nav>'
    };
});
hugo der hungrige
  • 12,382
  • 9
  • 57
  • 84
  • 1
    Thank you! I actually tracked down the problem up to the fact that if the element contains `#` then Dropdown event handler is applied to the detached HTML fragment (so the parent()...parent() ends on the div, not on the HTML) – Alex Netkachov Nov 14 '13 at 00:19