AngularJS Services for Views: Preparing the Example Project

For this chapter, I am going to continue to work with the example I created in Chapter 21 to demonstrate the different ways in which AngularJS applications can consume RESTful APIs. In the previous chapter, the focus was on managing the Ajax for the RESTful data, so you may not have noticed a rather nasty hack, which I will explain before showing how to resolve it.

1. Understanding the Problem

The application contains two view files, tableView.html and editorView.html, which I imported into the main products.html file using the ng-include directive.

The tableView.html file contains the default view for the application and lists the data from the server in a table element. I switch to the contents of the editorView.html file when the user is creating a new product or editing an existing one. When the operation is complete—or cancelled—I return to the contents of the tableView.html file again. The problem is the way that I manage the visibility of the contents of the view files. Listing 22-1 shows the products.html file.

Listing22-1. The Contents of the products.html File

<!DOCTYPE html>

<html ng-app=”exampleApp”>

<head>

<title>Products</title>

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

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

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

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

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

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

</head>

<body ng-controller=”defaultCtrl”>

<div class=”panel panel-primary”>

<h3 class=”panel-heading”>Products</h3>

<ng-include src=”‘tableView.html'” ng-show=”displayMode == ‘list'”></ng-include>

<ng-include src=”‘editorView.html'” ng-show=”displayMode == ‘edit'”></ng-include>

</div>

</body>

</html>

The issue is the use of the ng-show directive to control the visibility of the elements. To work out whether the contents of the view should be shown to the user, I check the value of a scope variable called displayMode and compare it to a literal value, like this:

<ng-include src=”‘tableView.html'” ng-show=”displayMode == ‘list'”></ng-include>

I set the value of displayMode in the controller behaviors defined in the products.js file to display the content I require. Listing 22-2 highlights how I set displayMode in the products.js file to switch between the views.

Listing 22-2. Setting the displayMode Value in the products.js File

angular.module(“exampleApp”, [“increment”, “ngResource”])

.constant(“baseUrl”, “http://localhost:5500/products/”)

.controller(“defaultCtrl”, function ($scope, $http, $resource, baseUrl) {

$scope.displayNode = “list”;

$scope.currentProduct = null;

$scope.productsResource = $resource(baseUrl + { id: “i®id” },

{ create: { method: “POST” }, save: { method: “PUT” } });

$scope.listProducts = function () {

$scope.products = $scope.productsResource.query();

}

$scope.deleteProduct = function (product) {

product.$delete().then(function () {

$scope.products.splice($scope.products.indexOf(product), 1);

});

$scope.displayMode = “list”;

}

$scope.createProduct = function (product) {

new $scope.productsResource(product).$create().then(function (newProduct) {

$scope.products.push(newProduct);

$scope.displayNode = “list”;

});

}

$scope.updateProduct = function (product) {

product.$save();

$scope.displayNode = “list”;

}

$scope.editOrCreateProduct = function (product) {

$scope.currentProduct = product ? product : {};

$scope.displayNode = “edit”;

}

$scope.saveEdit = function (product) {

if (angular.isDefined(product.id)) {

$scope.updateProduct(product);

} else {

$scope.createProduct(product);

}

}

$scope.cancelEdit = function () {

if ($scope.currentProduct && $scope.currentProduct.$get) {

$scope.currentProduct.$get();

}

$scope.currentProduct = {};

$scope.displayNode = “list”;

}

$scope.listProducts();

});

This approach works, but it presents a problem, which is that any component that needs to change the layout of the application needs access to the displayMode variable, which is assigned to the controller scope. This isn’t too much of a burden in such a simple application where the view is always managed by a single controller, but it doesn’t scale up when additional components need to control what the user sees.

What’s needed is a way to separate the view selection from the controller so that the application content can be driven from any part of the application, and that’s what I will show you in this chapter.

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 *