Introduction
In this article, we will discuss how about routing in Angular and how we can create single page applications using Angular routing module.
Link to complete series:
- Angular Tutorial - Part 1: Introduction to Angular.js
- Angular Tutorial - Part 2: Understanding Modules and Controllers
- Angular Tutorial - Part 3: Understanding and Using Directives
- Angular Tutorial - Part 4: Understanding and Implementing Filters
- Angular Tutorial - Part 5: Understanding and Implementing Services
- Angular Tutorial - Part 6: Building and Validating Data Entry Forms
- Angular Tutorial - Part 7: Understanding Single Page Applications and Angular Routing
Background
It is very rare that we have an application that contains only one single page. When I first heard the term "Single Page Application", I was rather baffled by it that how can we have everything placed in one single page of our application (yes, I was that lame once). So assuming that there could be some readers who are still at that stage where I was four years ago, I will try to explain this concept once again before talking about Angular routing.
From a traditional web development perspective, a page is a single HTML file. So if we have a static website, we essentially have a set of HTML pages linked to each other. Whenever a user navigates from one page to another, a request for the new page is sent to the server and the new requested HTML page is sent back to the client.
When we look the same concept from the server side technology perspective like ASP.NET web forms and PHP, we still find that these frameworks have a notion of pages, i.e., .ASPX, .PHP. Whenever user requests for a page, the server generates an HTML from these server pages and sends back the response HTML to the browser. Also, if we consider the MVC web frameworks like ASP.NET MVC and Ruby on Rails, these frameworks don't have a concept of physical pages but rather they invoke an action whenever a user requests for a page and then sends back the appropriate response HTML to the browser. But from the browser perspective, it is getting a new HTML page sent back to it.
So all these technologies can be said to contain multiple pages or multiple page web applications. These applications make a postback to the server on each user request and get back a new HTML page for the user. Now if we try to understand what a single page application is, it can simply be defined as an application that will load a single HTML page in the browser and on each subsequent request, the new data and new HTML is pulled from the server using AJAX. This gives the user an impression that only a single page is loaded in the browser and the needed app areas are getting refreshed/reloaded on his requests.
With this understanding of single page applications, let's try to see what Angular routing provides us. If we are using Angular routing module, we can have multiple HTML views/templates where each view is dedicated for some specific functionality. The routing module will facilitate the loading of these views asynchronously without causing any postback of the complete page. The route module will look for the routes in the URL, it will then capture the URL and check which view/template is configured to handle that route and finally, it will render that view on browser.
Using the Code
Let us now see how we can configure and use routing module in our application. The first important thing to note here is that the routing engine lives in a separate module and is also contained in a separate JavaScript file. So the first thing that we need to do is to include that file in our application.
Next, we need to inject the dependency of ngRoute
into our application.
myModule = angular.module('myAngularApplication', ['ngRoute']);
Next thing that we need to do is to configure the routing rules using the $routeProvidor
. Let's say we want to create an application that will have three views: Home
, About
and Contact
. We will show a simple menu bar on top of the page and three navigation links to navigate to these links. So let's first configure three routes home
, about
and contact
using the $routeProvidor
.
myModule = angular.module('myAngularApplication', ['ngRoute'])
.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when("/home", {
templateUrl: "home.html",
controller: "homeController"
})
.when("/about", {
templateUrl: "about.html",
controller: "aboutController"
})
.when("/contact", {
templateUrl: "contact.html",
controller: "contactController"
}).
otherwise({
redirect: '/home'
});
}]);
What the above code will do is that it will configure three routes and associate the specified view and controller for that route. Whenever a matching route is requested, the specified view will be loaded. The important thing to notice here is that I am also attaching the controller with the route too. This would mean that the specified controller will get associated with the specified view automatically and I don't have to put a ng-controller
in my view itself. We are also specifying an otherwise
condition so that if there is any unknown route in the URL, we push the user to our default route.
Now let us create these three view html files. These files will only contain the content of the page itself. So let's have a simple heading tag printing out the name of the view itself in these views.
Once this is done, let's have the controllers for the respective views. For now, the controllers will only be empty. In a real world scenario, they will contain the logic for rendering the view.
(function () {
var homeController = function ($scope) {
}
angular.module('myAngularApplication').controller('homeController', ["$scope", homeController]);
}());
(function () {
var contactController = function ($scope) {
}
angular.module('myAngularApplication').controller
('contactController', ["$scope", contactController]);
}());
(function () {
var aboutController = function ($scope) {
}
angular.module('myAngularApplication').controller('aboutController', ["$scope", aboutController]);
}());
So we have three dummy views and three dummy controllers ready with us. Now before we could use these views, we need to have the layout view of our application defined. The layout view is like the master page from the ASP.NET analogy. It defines the skeleton of my application and the common UI elements that should be present on all the pages. All the other views will be injected in this layout view by the routing engine based on the selected route.
To explain this layout view, I will use this image that I found on the Microsoft site.
In this image, the Angular layout view is like the master page. The views that we created in the previous section are just the content pages. Based on the route, the views will get injected in the layout view and the complete tailored view will be rendered to the user. So for our application, the layout view simply contains the top level menu. The area where the child view will be injected in the layout view will be created by the ng-view
directive. Let's see how our layout view looks like:
Now we have all the required pieces in place, let's run the application and see how the routing works.
And we have a sample application to see how routing works in Angular. The Routing module lets us create single page applications and define some basic routing for the application, but for more complex scenarios, it is not very much recommended. There is one more module UI Router from Angular where the routing is more state based rather than URL based. For complex routing scenarios, I highly recommend using UI router instead of this vanilla routing engine. But with this basic routing knowledge in place, perhaps understanding UI router will be much easier.
Points of Interest
In this article, we looked at the basics of routing in Angular and looked at how we can configure and use routing in Angular. The main intention of the article was to get familiar with how routing works. This has been written from a beginner's perspective. I hope it has been informative.
History
- 17th July, 2015: First version