Exercise 33: Custom Directives - jkneal/spring-angular-train GitHub Wiki
Learn how to build custom directives
- In
angular/client, create the directories 'components/cart' - In the cart directory, create a new file named cart-service.js
- In cart-service.js, create a new service named ‘CartService’. The service should take the service ‘$rootScope’ as a dependency
- Within this service, initialize a variable named ‘items’ to an empty array. Then expose the following service methods:
- addToCart – Take an object as an argument. If the argument is defined, set a property on the object named ‘inCart’ to true. Next add the object to the items array. Finally, broadcast an event on the root scope named ‘cartItemAdded’, and pass the items variable as an argument
- inCart – Take an object as an argument. If the argument is defined and has a property named ‘inCart’, and the value of this property is true, return true from this method. Otherwise, return false
- getItems – This method should take no arguments, and simply return the items array
- Next in the cart directory, create a new file named cart.js
- In cart.js, create a new directive named ‘cart’ associated with the ‘storeApp’ module
- Restrict the directive so it can only be used as an element name
- Set the ‘replace’ property on the directive definition object to true. This will replace the initial element containing the directive with the template (instead of replacing the element’s content)
- Make the directive have isolate scope. Add an attribute with name ‘checkoutPath’ that binds to the same scope property and accepts an expression for the attribute value
- Set the template URL for the directive as ‘components/cart/cart.html’
- Now add a directive controller that takes ‘$scope’ as a dependency. The controller should do the following:
- Initialize two scope properties ‘count’ and ‘total’ to 0
- A function (not a scope behavior) named ‘updateTotals’. The function should take an event object as the first parameter, and an array as the second parameter. Iterate through the array and calculate the $scope count and total properties. For the total, assume all array items have a property named ‘price’
- Finally, specify the ‘updateTotals’ function should be invoked (a listener) when the ‘cartItemAdded’ event occurs
-
Back in the cart directory, create a new file named cart.html
-
Add the content below to cart.html. After the text ‘Cart’, write out the $scope ‘count’ property in ‘()’ and then the $scope ‘total’ property formatted as a currency. For the button, set the href to be the value of the $scope property ‘checkoutPath’. Only show the button if this property has a value
<div class="label label-default"> <h4> Cart <a class="btn btn-success">checkout</a> </h4> </div>
-
In app.html, after the ‘close’ and ‘open’ links, invoke the directive. Specify the ‘checkoutPath’ as ‘#/checkout’. Also, add the CSS class ‘pull-right’
-
Modify the controller ‘storeCrtl’ (in store-controller.js) to take ‘CartService’ as a dependency. Expose the cart service ‘addToCart’ and ‘inCart’ methods as scope behaviors (with the same name)
-
Finally in products.html, add another button with class ‘btn btn-sm’ after the ‘remove’ button in the products table. Give the button the text ‘add to cart’. When the button is clicked, invoke the behavior ‘addToCart’ and pass the product (from the ngRepeat). Also, hide the button if the product is currently in the cart (use the behavior ‘inCart’)
-
Start the training application and go to the app home page
-
Click on the link 'Angular Exercises', and verify your page looks like the following:

-
Now click the ‘add to cart’ button for some of the records (including some you create). Verify the cart count and total are incremented correctly, and the ‘add to cart’ button is hidden