SportsStore – Navigation and Checkout with AngularJS: Starting the Checkout Process

Now that the routing configuration is in place, I am going to turn to the checkout process. My first task is to define a new controller called cartSummaryController, which I have placed in a new file called controllers/ checkoutControllers.js. Listing 7-14 shows the contents of the new file.

Listing 7-14. The Contents of the checkoutControllers.js File

angular.module(“sportsStore”)

.controller(“cartSummaryController”, function($scope, cart) {

$scope.cartData = cart.getProducts();

$scope.total = function () {

var total = 0;

for (var i = 0; i < $scope.cartData.length; i++) {

total += ($scope.cartData[i].price * $scope.cartData[i].count);

}

return total;

}

$scope.remove = function (id) {

cart.removeProduct(id);

}

});

The new controller is added to the sportsStore module and depends on the cart service. It exposes the contents of the cart through a scope property called cartData and defines behaviors to calculate the total value of the products in the cart and to remove a product from the cart. Using the features created by the controller, I can replace the temporary content in the checkoutSummary.html file with a summary of the cart. Listing 7-15 shows the changes I have made.

Listing 7-15. Revising the Contents of the checkoutSummary.html File

<h2>Your cart</h2>

<div ng-controller=”cartSummaryController”>

<div class=”alert alert-warning” ng-show=”cartData.length == 0″>

There are no products in your shopping cart.

<a href=”#/products” class=”alert-link”>Click here to return to the catalogue</a>

</div>

<div ng-hide=”cartData.length == 0″>

<table class=”table”>

<thead>

<tr>

<th>Quantity</th>

<th>Item</th>

<th class=”text-right”>Price</th>

<th class=”text-right”>Subtotal</th>

</tr>

</thead>

<tbody>

<tr ng-repeat=”item in cartData”>

<td class=”text-center”>{{item.count}}</td>

<td class=”text-left”>{{item.name}}</td>

<td class=”text-right”>{{item.price | currency}}</td>

<td class=”text-right”>{{ (item.price * item.count) | currency}}</td> <td>

<button ng-click=”remove(item.id)”

class=”btn btn-sm btn-warning”>Remove</button>

</td>

</tr>

</tbody>

<tfoot>

<tr>

<td colspan=”3″ class=”text-right”>Total:</td>

<td class=”text-right”>

{{total() | currency}}

</td>

</tr>

</tfoot>

</table>

<div class=”text-center”>

<a class=”btn btn-primary” href=”#/products”>Continue shopping</a>

<a class=”btn btn-primary” href=”#/placeorder”>Place order now</a>

</div>

</div>

</div>

There are no new techniques in this view. The controller is specified using the ng-controller directive, and I use the ng-show and ng-hide directives to show a warning when there are no items in the cart and a summary when there are. The ng-repeat directive is used to generate rows in a table for each product in the cart, and the details are displayed using data bindings. Each row contains unit and total pricing and a button that uses the ng-click directive to invoke the remove controller behavior and remove an item from the cart.

The two a elements at the end of the view allow the user to navigate elsewhere in the application:

<a class=”btn btn-primary” href=”#/products“>Continue shopping</a>

<a class=”btn btn-primary” href=”#/placeorder“>Place order now</a>

The Continue shopping button returns the user to the product list by navigating to the #/products path, and the Place order button navigates to a new URL path, #/placeorder, which I will configure in the next section.

1. Applying the Checkout Summary

The next step is to add a script element to the app.html file and define the additional routes that I will need to complete the checkout process, as shown in Listing 7-16.

Listing 7-16. Applying the Checkout Summary to the app.html File

<!DOCTYPE html>

<html ng-app=”sportsStore”>

<head>

<title>SportsStore</title>

<script src=”angular.js”></script>

<link href=”bootstrap.css” rel=”stylesheet” />

<link href=”bootstrap-theme.css” rel=”stylesheet” />

<script>

angular.module(“sportsStore”, [“customFilters”, “cart”, “ngRoute”])

.config(function ($routeProvider) {

$routeProvider.when(“/complete”, {

templateUrl: “/views/thankYou.html”

});

$routeProvider.when(“/placeorder”, {

templateUrl: “/views/placeOrder.html”

});

$routeProvider.when(“/checkout”, {

templateUrl: “/views/checkoutSummary.html”

});

$routeProvider.when(“/products”, {

templateUrl: “/views/productList.html”

});

$routeProvider.otherwise({

templateUrl: “/views/productList.html”

});

});

</script>

<script src=”controllers/sportsStore.js”></script>

<script src=”filters/customFilters.js”></script>

<script src=”controllers/productListControllers.js”></script>

<script src=”components/cart/cart.js”></script>

<script src=”ngmodules/angular-route.js”></script>

<script src=”controllers/checkoutControllers.js”></script>

</head>

<body ng-controller=”sportsStoreCtrl”>

<div class=”navbar navbar-inverse”>

<a class=”navbar-brand” href=”#”>SPORTS STORE</a>

<cart-summary />

</div>

<div class=”alert alert-danger” ng-show=”data.error”>

Error ({{data.error.status}}). The product data was not loaded.

<a href=”/app.html” class=”alert-link”>Click here to try again</a>

</div>

<ng-view />

</body>

</html>

The new routes associate URLs with views that I will create in the next chapter. Figure 7-7 shows the cart summary that is now presented when the user clicks the Checkout button on the cart widget.

Source: Freeman Adam (2014), Pro AngularJS (Expert’s Voice in Web Development), Apress; 1st ed. edition.

Leave a Reply

Your email address will not be published. Required fields are marked *