wonder95 wonder95 - 5 months ago 462
AngularJS Question

Navbar dropdown with Angular and ui-router won't work

I've been banging my head against this for a while, and for some reason I'm unable to get a simple bootstrap navbar dropdown to work with angular ui-router and ui-bootstrap (1.3.3, the latest). Here's my current code:

<div class="container">
<div class="row">
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Your <img class="logo-img" src="assets/images/formio-logo-lg.png"> application.</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a ui-sref="home">Home</a></li>
<li><a ng-class="{active:isActive('calendar')}" ui-sref="calendar" ng-show="authenticated">Duty Shifts</a></li>
<li><a ng-class="{active:isActive('eventIndex')}" ui-sref="eventIndex" ng-show="authenticated">Events</a></li>
<li><a ng-class="{active:isActive('trainingIndex')}" ui-sref="trainingIndex" ng-show="authenticated">Training</a></li>
<li><a ng-class="{active:isActive('shiftIndex')}" ui-sref="shiftIndex" ng-show="authenticated">Shifts List</a></li>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Admin<span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a ui-sref="trainingCreate">Add Training</a></li>
<li><a ui-sref="eventCreate">Add Event</a></li>
<li><a ui-sref="shiftCreate">Add Shift</a></li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li ng-if="authenticated"><a href="#" ng-click="logout()"><span class="glyphicon glyphicon-off" aria-hidden="true"></span> Logout</a></li>
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
</div>
<div id="content">
<div class="row" ng-cloak>
<uib-alert ng-repeat="alert in alerts" type="{{alert.type}}" close="closeAlert($index)">{{alert.message}}</uib-alert>
</div>
<div ui-view></div>
</div>
</div>


With this setup, I see the Admin dropdown menu, but clicking does nothing, whether or not I have a ui-sref attribute.

If I do everything suggested in the migration guide for dropdowns, like so:

<li uib-dropdown>
<a ui-sref="home" uib-dropdown-toggle uib-dropdown role="button" aria-haspopup="true" aria-expanded="false">Admin<span class="caret"></span></a>
<ul uib-dropdown-menu>
<li><a ui-sref="trainingCreate">Add Training</a></li>
<li><a ui-sref="eventCreate">Add Event</a></li>
<li><a ui-sref="shiftCreate">Add Shift</a></li>
</ul>
</li>


it still doesn't work. I'm sure I'm missing something obvious, but I'm not sure what. I've looked at the ui-navbar package, but I don't want to have to re-tool everything just for a dropdown if I don't have to.

What am I doing wrong? And yes, I do have ui.bootstrap and ui.router injected in my app definition.

Thanks.

Answer

Here is working plunker based on your code.

The admin dropdown inside the navbar looks like:

<li class="dropdown" uib-dropdown>
    <a class="dropdown-toggle" uib-dropdown-toggle>
        <i class="fa fa-cogs"></i> Admin <span class="caret"></span>
    </a>
    <ul class="dropdown-menu" role="menu">
        <li><a ui-sref="training" ng-click='navCollapsed = true'>Add Training</a></li>
    </ul>
</li>

When you click on training, it loads training.html in the div ui-view as a single page application. Note that in the ui-sref I added a ng-click to collapsed the main navigation.

The full navbar looks like:

 <nav class="navbar navbar-inverse " role="navigation">
    <!-- Brand and toggle get grouped for better mobile display -->
    <div class="navbar-header">

      <button type="button" class="navbar-toggle" ng-init="navCollapsed = true" ng-click="navCollapsed = !navCollapsed">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
      <a class="navbar-brand" href="#">Brand</a>
    </div>

    <!-- Collect the nav links, forms, and other content for toggling -->
    <div class="collapse navbar-collapse" ng-class="!navCollapsed && 'in'">

      <ul class="nav navbar-nav">
        <li><a ui-sref="home"  ng-click='navCollapsed = true'>Home</a></li>
        <li><a ui-sref="home"  ng-click='navCollapsed = true'>Link</a></li>
        <li class="dropdown" uib-dropdown>
          <a class="dropdown-toggle" uib-dropdown-toggle>
            <i class="fa fa-cogs"></i> Admin
            <span class="caret"></span>
          </a>
          <ul class="dropdown-menu" role="menu">
            <li><a ui-sref="training" ng-click='navCollapsed = true'>Add Training</a></li>
          </ul>
        </li>

      </ul>
    </div>
    <!-- /.navbar-collapse -->
  </nav>

I configure the routing like this:

angular.module('plunker', ['ui.router', 'ui.bootstrap'])
.config(function($stateProvider, $urlRouterProvider) {

    $urlRouterProvider.otherwise('/home');

    $stateProvider
    .state('home', {
      url: '/home'
    })

    .state('training', {
      url: '/training',
      templateUrl: 'training.html',
    });

  })

Let us know if that helps. Best.

Comments