Wednesday, January 1, 2014

Routing in AngularJS

In the previous sample we saw a basic Angular page. Let's expand on that a bit to have a simple orders application.

Let's start with a simple HTML page, that has 3 links on it with the usual Angular stuff

index.html

<!DOCTYPE html>
<html ng-app="ordersApp">
<head>
<script type="text/javascript" src="http://code.angularjs.org/1.2.0/angular.min.js"></script>
<script type="text/javascript" src="http://code.angularjs.org/1.2.0/angular-route.js"></script>
<script type="text/javascript" src="ordersApp.js"></script>
<title>Make your orders here</title>
</head>
<body ng-controller="indexController">
<p>Current scope is {{ scope }} </p>
<div ng-show="{ scope=='index' }" ng-controller="indexController">
<h1>{{ heading }}</h1>
<h3>How it works?</h3>
<p>As soon as the item that needs to be purchased it added, item is registered in a CLOUD database that will in turn alert me/subscriber on their iPhone. It will also enable the end user to check for the item registerd and from where. If they have enabled location services, then when they reach the store, it will buzz on the items that need to be purchased from the store. Is that not fascinating enough for you?</p>
<br/>
<h3>What next?</h3>
<p>Once you purchase the item you should be provided with a facility to register the cost of the item. Next time when you purchase the same item from say a different store, you can the compare prices to check on which is the best and chepesr place for you to purchase the item. Did I say best....Yes, apparently I did. You will also be provided with a choice to select the quality of the item you purchased in the store. This will eventually enable you to ascerain the quality of the product. Not just the price alone. If that's not exciting in daily life, what is?</p>
<p>Now, let's dive in.....go on and give it a spin</p>
<div >
<table>
<tr>
<td>
{{ addOrderText }} <a href="addorder">here</a>
</td>
</tr>
<tr>
<td>
{{ listOrdersText }} <a href="listorders">here</a>
</td>
</tr>
<tr>
<td>
{{ searchOrderText }} <a href="searchorder">here</a>
</td>
</tr>
</table>
</div>
</div>
</body>

Here's the sample JS controller for the index page

indexController in orderApp.js

var ordersApp = angular.module('ordersApp', ['ngRoute']);

function indexController($scope) {
$scope.heading="A place to register all items that should be purchased";
$scope.addOrderText="Place you new orders";
$scope.listOrdersText = "Check all your orders";
$scope.searchOrderText="Search for an order";
$scope.scope="index";
}

Let's start by creating separate HTML files for each of the functionalities

addorder.html

<!DOCTYPE html>
<html ng-app="ordersApp">
<head>
<script type="text/javascript" src="http://code.angularjs.org/1.2.0/angular.min.js"></script>
<script type="text/javascript" src="http://code.angularjs.org/1.2.0/angular-route.js"></script>
<script type="text/javascript" src="ordersApp.js"></script>
<script type="text/javascript" src="addOrderController.js"></script>
<title>Place your order here</title>
</head>
<body ng-controller="addOrderController">
<h2>{{ heading }}</h2>
<div>
<p>Make sure the items you register here are clear and perceivable. If you are confused let me know, we could add a description/text field here to make it more easy for you.</p>
</div>
<div>
<table>
<tr>
<td><a href="index">Home</a></td>
<td><a href="listorders">List</a></td>
<td><a href="searchorder">Search</a></td>
</tr>
</table>

</div>
<br/>
<form name="orderForm">
<table>
<tr>
<td>Item</td>
<td><input type="text"></td>
</tr>
<tr>
<td>Quantity</td>
<td><input type="text"></td>
</tr>
<tr>
<td>From store</td>
<td><input type="text"></td>
</tr>
<tr>
<td><button type="submit">Add</button></td>
<td><button>Clear/Cancel</button></td>
</tr>
</table>
</form>
</body>
</html>

listorders.html

<!DOCTYPE html>
<html ng-app="ordersApp">
<head>
<script type="text/javascript" src="http://code.angularjs.org/1.2.0/angular.min.js"></script>
<script type="text/javascript" src="http://code.angularjs.org/1.2.0/angular-route.js"></script>
<script type="text/javascript" src="ordersApp.js"></script>
<script type="text/javascript" src="listOrdersController.js"></script>
<title>Check all orders you placed</title>
</head>
<body ng-controller="listOrdersController">
<div>
<p><h2>{{ heading }}</h2></p>
</div>
<div>
<table>
<tr>
<td><a href="index">Home</a></td>
<td><a href="listorders">List</a></td>
<td><a href="searchorder">Search</a></td>
</tr>
</table>

</div>
<br/>
<table>
<tr>
<th>Item</th>
<th>Quantity</th>
<th>Store</th>
<th>Operation</th>
</tr>
</table>
</body>
</html>

searchorder.html

<!DOCTYPE html>
<html ng-app="ordersApp">
<head>
<script type="text/javascript" src="http://code.angularjs.org/1.2.0/angular.min.js"></script>
<script type="text/javascript" src="http://code.angularjs.org/1.2.0/angular-route.js"></script>
<script type="text/javascript" src="ordersApp.js"></script>
<script type="text/javascript" src="searchOrderController.js"></script>
<title>Check all orders you placed</title>
</head>
<body ng-controller="searchOrderController">
<form name="searchForm">
<p><h2>{{ heading }}</h2></p>
<div>
<table>
<tr>
<td><a href="index">Home</a></td>
<td><a href="listorders">List</a></td>
<td><a href="searchorder">Search</a></td>
</tr>
</table>

</div>
<br/>
<table>
<tr>
<td>Item</td>
<td><input type="text"></td>
<td>From store</td>
<td><input type="text"></td>
<td><button type="submit">Search</button></td>
</tr>
</table>
</form>
<p>Results...</p>
<div>
<table>
<tr>
<th>Item</th>
<th>Quantity</th>
<th>Store</th>
<th>Operation</th>
</tr>
</table>
</div>
</body>
</html>

Note: All of the above HTML code are not perfect or even close to perfection. We will improve the code as we go along and of course our objective here is not HTML, but Angular JS. Feel free to chip in with your ideas and code improvements. I am forever open for that.

I prefer separate JS file for each controller and here's what I have in each of them

addOrderController.js

function addOrderController($scope) {
$scope.heading="Place your order here";
$scope.scope="addorder";
}

listOrdersController.js

function listOrdersController($scope) {
$scope.heading = "List of all item you ordered";
$scope.scope = "listorder";
}

searchOrderController.js

function searchOrderController($scope) {
$scope.heading = "Search For your orders";
$scope.scope = "searchorder";
}

Now that we have the basic HTML and the controller, our next step will be to introduce routing logic. To know how the routing works I suggest you read from here

Let's start with updating a router config in indexController.js. Pretty simple, when the user taps on addorder, we redirect to the respective HTML and assciate a controller for the HTML. Please make sure you tie the right controller with the HTML. If there is a mis-match on the controllers you will see some bizzare errors that are difficult to debug. Now you are all set with the routing mechanism

Updated orderApp.js

var ordersApp = angular.module('ordersApp', ['ngRoute']);

function indexController($scope) {
$scope.heading="A place to register all items that should be purchased";
$scope.addOrderText="Place you new orders";
$scope.listOrdersText = "Check all your orders";
$scope.searchOrderText="Search for an order";
$scope.scope="index";
}

ordersApp.config(['$routeProvider',
  function($routeProvider) {
  console.log($routeProvider);
    $routeProvider.
      when('/addorder', {
        templateUrl: './addorder.html',
        controller: 'addOrderController'
      }).
      when('/listorders', {
      templateUrl: './listorders.html',
      controller: 'listOrdersController'
      }).
      when('/searchorder', {
      templateUrl: './searchorder.html',
      controller: 'searchOrderController'
      }).
      otherwise({
        redirectTo: '/index.html'
      });
  }]);

Although this is one way of hadling different views, if you notice there is something big missing. What if we want all of the sub-views to be displayed in the index view itself, based on the selection choice. Sure we could do that too. In order to achieve that we have to make a few simple changes
our links in the index page should be local links, we should also add a ng-view in index.html and ensure you import the needed scripts to index.html. Here is the change for that. Try it out, and I am sure this will be a seed for a lot more things that you are/were thinking from the previous sample.

index.html for inline linking of views

<!DOCTYPE html>
<html ng-app="ordersApp">
<head>
<script type="text/javascript" src="http://code.angularjs.org/1.2.0/angular.min.js"></script>
<script type="text/javascript" src="http://code.angularjs.org/1.2.0/angular-route.js"></script>
<script type="text/javascript" src="ordersApp.js"></script>
<script type="text/javascript" src="addOrderController.js"></script>
<script type="text/javascript" src="listOrdersController.js"></script>
<script type="text/javascript" src="searchOrderController.js"></script>
<title>Make your orders here</title>
</head>
<body ng-controller="indexController">
<p>Current scope is {{ scope }} </p>
<div ng-show="{ scope=='index' }" ng-controller="indexController">
<h1>{{ heading }}</h1>
<h3>How it works?</h3>
<p>As soon as the item that needs to be purchased it added, item is registered in a CLOUD database that will in turn alert me/subscriber on their iPhone. It will also enable the end user to check for the item registerd and from where. If they have enabled location services, then when they reach the store, it will buzz on the items that need to be purchased from the store. Is that not fascinating enough for you?</p>
<br/>
<h3>What next?</h3>
<p>Once you purchase the item you should be provided with a facility to register the cost of the item. Next time when you purchase the same item from say a different store, you can the compare prices to check on which is the best and chepesr place for you to purchase the item. Did I say best....Yes, apparently I did. You will also be provided with a choice to select the quality of the item you purchased in the store. This will eventually enable you to ascerain the quality of the product. Not just the price alone. If that's not exciting in daily life, what is?</p>
<p>Now, let's dive in.....go on and give it a spin</p>
<div >
<table>
<tr>
<td>
{{ addOrderText }} <a href="#addorder">here</a>
</td>
</tr>
<tr>
<td>
{{ listOrdersText }} <a href="#listorders">here</a>
</td>
</tr>
<tr>
<td>
{{ searchOrderText }} <a href="#searchorder">here</a>
</td>
</tr>
</table>
</div>
</div>
<div ng-view></div>
</body>

Our next objective will be to handle a form that's been submitted, and do some basic validation on it. Thanks for you time. Don't forget to sign-off with you comments

No comments: