All web apps will require more than one page or view, and Angular is well-equipped to handle this with its router. You may be familiar with routing in server-side frameworks, such as Ruby on Rails or Laravel. Angular’s is, of course, entirely on the client side and all the magic happens within the HTML file our browser is pointed to.

In this Tutorial, we’ll take a look at how we can create static routes as well as routes containing parameters. We’ll also discover some of the pitfalls you might face.

Before we begin, let’s plan out exactly what routes we’re going to need for our contacts manager:

  • Index: This is going to be our main page, which will list all of our contacts in a table
  • View Contact: Here, we’ll be able to see the contact in more detail and edit any of the information it presents
  • Add Contact: This will include a form that will allow us to add a contact to the manager

These are all of our essential routes; so let’s take a look at how we can create them.

Installing ngRoute

Since angularjs 1.2, the router has been packaged as a separate module outside of Angular’s core. The file we’re looking for—angular-route.min.js—can be downloaded from Angular’s website below the Extras section within the download window.

Installing ngRoute

Once you’ve got the download, drag it into your project’s js directory and include it in the page after angularjs:

<script src="assets/js/angular-route.min.js"></script>

We also need to let our module know that we want to utilize the router. We can do this by adding it to the module’s dependency list. We can have as many dependencies as we like; currently all we need to include is ngRoute:

angular.module('contactsMgr', ['ngRoute'])

Creating basic routes

As we’ve already discovered, in order to configure the router within angularjs, a module is required.

Routes are created within the config method of our application’s module:

angular.module('contactsMgr', ['ngRoute'])

The method accepts an anonymous function that we can inject our required $routeProvider service into. This service has just two methods: when and otherwise. To add a route, we use the when method, which accepts two parameters: the path as a string and options for the route as an object:

angular.module('contactsMgr', ['ngRoute'])
    $routeProvider.when('/', {});    

There are two properties within our route options object that we’re particularly interested in: controller and templateUrl. The controller property calls an existing controller constructor or defines a new one using an anonymous function. Meanwhile, the templateUrl property allows us to define the path to an HTML file that will house our entire markup for that view. Alternatively, we could define the template directly within the route object. However, things can get messy fairly quickly that way and are only really recommended for one- or two-line templates.

Let’s take a look at the route we’re going to define for our index page:

$routeProvider.when('/', {
    controller: 'indexCtl',
    templateUrl: 'assets/partials/index.html'

The path to the template is relative to our base HTML file; hence, it includes the assets directory in the path. We can now go ahead and create that HTML template. Angular refers to these as partials and we’ll be using them for all of our views.

The controller argument within our route is optional, but we’ve included it as we’re going to need one for our application. Let’s create that controller to allow us to build models and functions exclusively for our index view.

Within our controller.js file, let’s can chain this onto the end:

.controller('indexCtrl', function($scope){


Let’s quickly add our second route with our config method. This will house our add-contact form:

$routeProvider.when('/', {
    controller: 'indexCtl',
    templateUrl: 'assets/partials/index.html'

.when('/add-contact', {
    controller: 'addCtl',
    templateUrl: 'assets/partials/add.html'

Just as we can with controllers, we can chain our routes. Now just create the relevant controller and partial:

.controller('addCtl', function($scope){


The last thing we need to do before Angular kicks the router into action is include the ng-view directive on our page. This pulls in the partial we’ve defined in the route.


Note: You can only include ng-view once on per page.

<div class="container">

This directive can be included as its own element. I’ve opted to include the directive as an element in my root index.html file. If you have anything in your container already, clear it out and replace it with ng-view instead.

If you open the project in your browser, you’ll notice that the route has been appended to the URL with the # symbol preceding it. Unfortunately, if you’re using Chrome, it’s likely that the partials will fail to load. If you open up the console, you’ll probably see a similar error to the following:

Cross origin requests are only supported for HTTP.

There are a couple of ways to fix this. We can either load the code up on a web server, or if we’re using Chrome, we can run the browser using a flag to enable cross-origin requests over the file:// protocol on OS X or over c:/ on Windows.

On OS X, run the following in Terminal:

open -a 'Google Chrome' --args -allow-file-access-from-files

On other *nix-based systems run the following:

google-chrome  --allow-file-access-from-files

On Windows, you need to edit the desktop shortcut to add a flag at the end of the Target:

C:\ ... \Application\chrome.exe --allow-file-access-from-files

If you don’t want to run Chrome with a flag, you can run the contact manager on a web server. You could use the web server built into Python or PHP, or a full-stack app like MAMP or WAMP.

Change directory into your project and run the following command to server your application using Python’s web server:

python -m SimpleHTTPServer 8000

You can now navigate to localhost:8000 in your browser to view your app. Alternatively, if you would prefer to run PHP’s web server, you can do that with the following:

php -S localhost:8000