SportsStore – Orders and Administration with AngularJS: Placing Orders

Even though the state of the button element is controlled by form validation, clicking the button has no effect, and that’s because I need to finish off the SportsStore application by allowing the user to submit orders. In the sections that follow, I’ll extend the database provided by the Deployd server, send order data to the server using an Ajax request, and display a final thank-you message to complete the process.

1. Extending the Deployd Server

I need to extend the Deployd configuration to capture the orders that the SportsStore application will submit. Using the Deployd dashboard (which I first used in Chapter 6), click the large green plus button and select Collection, as shown in Figure 8-4.

Set the name of the new collection to /orders and click the Create button. The Deployd dashboard will display the property editor that I described in Chapter 6 when creating the products collection. Define the properties shown in Table 8-1.

Pay particular attention to the type of the giftwrap and products properties—they are not the same type as the other properties, and you’ll get some odd results if you don’t define them correctly. When you are finished, the property list for the orders collection should match that shown in Figure 8-5.

2. Defining the Controller Behavior

The next step is to define the controller behavior that will send details of an order to the Deployd server using an Ajax request. I could define this functionality in a number of different ways—as a service or in a new controller, for example. This flexibility is one of the hallmarks of working with AngularJS. There is no absolute right or wrong when it comes to the structure of an AngularJS application, and you will develop your own style and set of preferences as your experience builds. I am going to keep things simple and add the behavior I need to the top-level sportsStore controller, which already contains the code that makes the Ajax request to load the product data. Listing 8-6 shows the changes I have made.

Listing8-6. Sending the Order to the Server in the sportsStore.js File

angular.module(“sportsStore”)

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

.constant(“orderUrl”, “http://localhost:5500/orders”)

.controller(“sportsStoreCtrl”, function ($scope, $http, $location,

dataUrl, orderUrl, cart) {

$scope.data = {

};

$http.get(dataUrl)

.success(function (data) {

$scope.data.products = data;

})

.error(function (error) {

$scope.data.error = error;

});

$scope.sendOrder = function (shippingDetails) {

var order = angular.copy(shippingDetails);

order.products = cart.getProducts();

$http.post(orderUrl, order)

.success(function (data) {

$scope.data.orderId = data.id;

cart.getProducts().length = 0;

})

.error(function (error) {

$scope.data.orderError = error;

}).finally(function () {

$location.path(“/complete”);

});

}

});

Deployd will create a new object in the database in response to a POST request and will return the object that it has created in the response, including the id attribute that has been generated to reference the new object.

Knowing this, you can see how the new additions to the controller operate. I have defined a new constant that specifies the URL that I will use for the POST request and added a dependency for the cart service so that I can get details of the products that the user requires. The behavior I added to the controller is called sendOrder, and it receives the shipping details for the user as its argument.

I use the angular.copy utility method, which I describe in Chapter 5, to create a copy of the shipping details object so that I can safely manipulate it without affecting other parts of the application. The properties of the shipping details object—which are created by the ng-model directives in the previous section—correspond to the properties that I defined for the orders Deployd collection, and all I have to do is define a products property that references the array of products in the cart.

I use the $http.post method, which creates an Ajax POST request to the specified URL and data, and I use the success and error methods that I introduced in Chapter 5 (and which I describe fully in Chapter 20) to respond to the outcomes from the request. For a successful request, I assign the id of the newly created order object to a scope property and clear the contents of the cart. If there is a problem, I assign the error object to the scope so that I can refer to it later.

I also use the then method on the promise returned by the $http.post method. The then method takes a function that is invoked whatever the outcome of the Ajax request. I want to display the same view to the user whatever happens, so I use the then method to call the $location.path method. This is how the path component of the URL is set programmatically, and it will trigger a change of view through the URL configuration that I created in Chapter 7. (I describe the $location service in Chapter 11 and demonstrate its use with URL routing in Chapter 22.)

3. Calling the Controller Behavior

To invoke the new controller behavior, I need to add the ng-click directive to the button element in the shipping details view, as shown in Listing 8-7.

Listing 8-7. Adding a Directive to the placeOrder.html File

<div class=”text-center”>

<button ng-disabled=”shippingForm.$invalid”

ng-click=”sendOrder(data.shipping)”

class=”btn btn-primary”>

Complete order

</button>

</div>

4. Defining the View

The URL path that I specify after the Ajax request has completed is /complete, which the URL routing configuration maps to the file /views/thankYou.html. I created this file, and you can see the contents of it in Listing 8-8.

Listing 8-8. The Contents of the thankYou.html File

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

Error ({{data.orderError.status}}). The order could not be placed.

<a href=”#/placeorder” class=”alert-link”>Click here to try again</a>

</div>

<div class=”well” ng-hide=”data.orderError”>

<h2>Thanks!</h2>

Thanks for placing your order. We’ll ship your goods as soon as possible.

If you need to contact us, use reference {{data.orderId}}.

</div>

This view defines two different blocks of content to deal with success and unsuccessful Ajax requests. If there has been an error, then details of the error are displayed, along with a link that takes the user back to the shipping details view so they can try again. If the request is successful, then the user is shown a thank-you message that contains the id of the new order object. You can see the successful outcome in Figure 8-6.

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 *