When coding, it is good practice to reduce duplicating your code as much as possible. When you build a website, multiple pages may be grouped with specific layouts that are used any number of times. You don’t want to duplicate your layout code across these pages.
A common thing to do in web design is to use templating. This exists similarly across many web languages, but in this example I’m going to demonstrate how to do this with AngularJS and the UI-Router extension.
To be specific we are going to accomplish the following:
With this knowledge you’d be able to create a multi-layout project. In this project, we are going to have the following directory and file structure:
templates
settings.html
account.html
profile.html
js
angular-ui-router.min.js
app.js
index.html
Start by downloading the UI-Router library and including it in your project. Your index.html page should look something like this:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.27/angular.min.js"></script>
<script src="js/angular-ui-router.min.js"></script>
<script src="js/app.js"></script>
</head>
<body ng-app="example">
Index Level
<div ui-view></div>
</body>
</html>
Notice the index.html page has all our JavaScript and CSS includes. It also has the following two lines:
Index Level
<div ui-view></div>
I added the text Index Level
to make it obvious that the index.html code is used in our page. It represents level one of three in our nesting line. The ui-view
line is where the next layer will display.
Now let’s crack open the settings.html page. This page will pretty much just contain a menu system for navigating between settings pages. Often websites will have a separate UI system for settings pages, but yet it will keep a trend.
<h1>Settings Level</h1>
<hr/>
<a ui-sref="settings.profile">Show Profile</a>
<a ui-sref="settings.account">Show Account</a>
<div ui-view></div>
Notice the lines above. Two are responsible for loading the next level of nesting which is nesting level three. The last line is where level three will be loaded into. I threw a line of code in there to show us that the settings level was loaded.
Now we are going to add the code for the third level of nesting. Open profile.html and add the following lines:
Profile Level
Do the same for account.html, but this time add the following content:
Account Level
When a third level page is loaded it will show the root level, settings level, and content level content. So at this point we only did the UI work. We still need to code the JavaScript that will be responsible for tying everything together.
Open the app.js file and add the following code:
var example = angular.module("example", ['ui.router']);
example.config(function($stateProvider, $urlRouterProvider) {
$stateProvider
.state('settings', {
url: '/settings',
templateUrl: 'templates/settings.html'
})
.state('settings.profile', {
url: '/profile',
templateUrl: 'templates/profile.html',
controller: 'ProfileController'
})
.state('settings.account', {
url: '/account',
templateUrl: 'templates/account.html',
controller: 'AccountController'
});
$urlRouterProvider.otherwise('/settings/profile');
});
Time to break down what the above code means. Take a look at the following lines:
.state('settings', {
url: '/settings',
templateUrl: 'templates/settings.html'
})
The above state represents the settings level layout. It will never be called directly because it is nothing more than a layout. It cannot exist on its own in the scenario that we’re building.
.state('settings.profile', {
url: '/profile',
templateUrl: 'templates/profile.html',
controller: 'ProfileController'
})
In the above code, notice in particular settings.profile
. This has very specific meaning. It means that we are going to call the settings
state as well as the profile
state. It is how we accomplish nesting. States are object based so every time we add to the parent settings element it means we are going to render the page inside of it.
A video version of this article can be seen below.