Search code examples
angularjsangular-ui-routermean-stackmeanjsngroute

How to have angular nav-bars and ng-route together in a MEAN Stack app?


I wish to create a MEAN Stack app, in which the front-end UI has navigation bar (nav-bar) containing three navigation links to three different pages.

On clicking the tabs/navigation items, the corresponding page should get open. Can this be done using ngRoute? If yes, then how?

Moreover, I will use that app in MEAN Stack app. I tried doing this using ui-router; it worked when deployed the app on tomcat. But whenever code is deployed on MEAN Stack, it doesn't work.

Can any one please tell why is it happening?

File Structure:

Project Name
|-- client
|   |-- js
|   |   `-- app.js
|   |-- templates
|   |   |-- about.html
|   |   `-- home.html
|   `-- views
|       `-- index.html
|-- server
|-- node_modules
|-- server.js
`-- package.json

index.html

<!DOCTYPE html>
<html>
<head>

    <!-- CSS (load bootstrap) -->
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">
    <style>
        .navbar { border-radius:0; }
    </style>

    <!-- JS (load angular, ui-router, and our custom js file) -->
    <script src="http://code.angularjs.org/1.2.13/angular.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.8/angular-ui-router.min.js"></script>
    <script src="/client/js/app.js"></script>
</head>

<!-- angular app  -->
<body ng-app="routerApp">

<!-- NAVIGATION -->
<nav class="navbar navbar-inverse" role="navigation">
    <div class="navbar-header">
        <a class="navbar-brand" ui-sref="#">AngularUI Router</a>
    </div>
    <ul class="nav navbar-nav">
        <li><a ui-sref="home">Home</a></li>
        <li><a ui-sref="about">About</a></li>
    </ul>
</nav>


<div class="container">
    <div ui-view></div>
</div>

</body>
</html>

app.js

var routerApp = angular.module('routerApp', ['ui.router']);

routerApp.config(function($stateProvider, $urlRouterProvider) {

    $urlRouterProvider.otherwise('/home');

    $stateProvider

        .state('home', {
            url: '/home',
            templateUrl: '/client/templates/home.html'
        })

        .state('about', {
            url: '/about',
            templateUrl: '/client/templates/about.html'

        });

});

server.js

var express           = require('express'),
    app               = express();
    bodyParser        = require('body-parser');

app.use(bodyParser());

app.get('/', function (req, res) {
  res.sendfile(__dirname + '/client/views/index.html');
});

 app.use('/js', express.static(__dirname + '/client/js'));

app.listen(3000, function() {
  console.log('I\'m Listening...');
})

Solution

  • First, what error are you getting in the console? At first glance, I see that some of your resources are missing the protocol in the uri.

    Now you are using uiRoute which gives you more flexibility than ngRoute. If you still wish to go with ngRoute, you need first to load the ngRoute module in your application and edit the routing:

    (function(){
    
            var app = angular.module('module_name', ['ngRoute']);
    
            app.config(['$routeProvider',function($routeProvider) {
                $routeProvider
                .when('/url1', {
                    controller: 'nameOfController',
                    controllerAs: 'referenceToController',
                    templateUrl: 'referenceToView',
                    resolve: { // run all these methods before loading project
                        method1: function(){
                            return value1
                        },
                        method2: function(){
                            return value1
                        }
                    }
                })
                .otherwise('/url2');
            }])
    
        }());
    

    In order to achieve the desired functionality with ngRoute, you have several options:

    1- Use ng-href directive: you can add the ng-href directive to the DOM element (your menu items) like this:

    <li><a ng-href="/#/home">Home</a></li>
    

    2- Use $location service in the controller: you can add a click event listener to the DOM and call the path() method in the $location service like this (you need to create your controller first):

      $("a[ui-sref='home']").on("click", function(){ $location.path("/#/home");});
    

    3- Build your own directive: probably unnecessary if all you want is a simple menu bar. But if you wish to go beyond the basic behavior (like updating some data in the app for DOM manipulation or business logic purposes):

    <li><a ui-sref="home" my-costume-click-directive>Home</a></li>
    
    angular.module(app).directive('myCostumeClickDirective', function(){
        return {
            link: function(scope, elm, attr, controller, transclude) { 
                  // your event listeners and methods go here
            }
        }
      });