Node Shopping Cart

43
8/9/2019 Node Shopping Cart http://slidepdf.com/reader/full/node-shopping-cart 1/43 28. Creating Your Own Shopping Cart In this chapter you get to look at another practical implementation example of a shopping cart. The reason that a shopping cart example was chosen is because it is very common and familiar so the concepts will be easy to pick up on throughout the chapter. Also the shopping cart example will allow us to look at one way to utilize the ability to switch  between views in AngularJS as you navigate through the checkout process. The shopping cart you will create provides most of the necessary functionality however it is not intended for production. There is missing  validation and error handling in areas to make the pro!ect reasonable to fit inside a book example. "owever the pro!ect will take you through the  basic steps and provide you with fundamental understanding of how the #ode.JS $ongo%& and AngularJS operates. Project Description The implementation in this chapter is a fairly basic shopping cart that allows you to add items remove items and then go through the checkout process and view your orders. The example provides most of the basic functionality that is re'uired for a shopping cart however it is not intended for production use but rather as a teaching aid. (eep in mind that the cart does not actually link to a credit card  verification service to process payments. That goes beyond the scope of the pro!ect. There is still a fair amount of work to take this pro!ect and make it into something that could be used in production.  Also login authentication and session management are also omitted from the pro!ect since that was already covered in )hapter *+ and would add additional code to sift through to understand the shopping cart example. The example is hard coded to a user with a userid of customerA.  ,ou will see that places where the authenticated user would be used customerA is hard coded. The general logic flow of the example is as follows-

Transcript of Node Shopping Cart

Page 1: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 1/43

28. Creating Your Own Shopping Cart

In this chapter you get to look at another practical implementation

example of a shopping cart. The reason that a shopping cart example waschosen is because it is very common and familiar so the concepts will beeasy to pick up on throughout the chapter. Also the shopping cartexample will allow us to look at one way to utilize the ability to switch

 between views in AngularJS as you navigate through the checkoutprocess.

The shopping cart you will create provides most of the necessaryfunctionality however it is not intended for production. There is missing

 validation and error handling in areas to make the pro!ect reasonable tofit inside a book example. "owever the pro!ect will take you through the basic steps and provide you with fundamental understanding of how the#ode.JS $ongo%& and AngularJS operates.

Project Description

The implementation in this chapter is a fairly basic shopping cart thatallows you to add items remove items and then go through the checkoutprocess and view your orders. The example provides most of the basic

functionality that is re'uired for a shopping cart however it is notintended for production use but rather as a teaching aid.

(eep in mind that the cart does not actually link to a credit card verification service to process payments. That goes beyond the scope ofthe pro!ect. There is still a fair amount of work to take this pro!ect andmake it into something that could be used in production.

 Also login authentication and session management are also omitted

from the pro!ect since that was already covered in )hapter *+ and wouldadd additional code to sift through to understand the shopping cartexample. The example is hard coded to a user with a userid of customerA.

 ,ou will see that places where the authenticated user would beused customerA is hard coded.

The general logic flow of the example is as follows-

Page 2: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 2/43

1. The root page contains a list of prints that can be purchased.

2. The user clicks on a print to view details where they can add it to thecart. $ultiple items can be added to the cart. The top link to the cartshows the number of items in the cart.

3. The user clicks on the cart and can see the items. They can change the'uantity remove items continue shopping or checkout.

4. n checkout the customer is presented with shipping informationpage.

5. Then the customer is presented with billing information including the billing address and credit card data.

6. /hen the customer clicks to submit the billing information a review of the validated transaction is displayed and the user can select the final

purchase.7. After the final purchase is clicked the user is shown a list of theirorders including the recently completed order.

Libraries Used

The pro!ect in this chapter uses the following add on #ode.!s #0$modules. ,ou will need to install them into your pro!ect directory if youintend to follow along with the example code-

1 express: 2sed as the main web server for the pro!ect.1 ejs: 2sed to render the "T$3 templates.1  mongodb: 2sed to access the $ongo%& database.1  mongoose: 2sed to provide the structured data model.

This code in this chapter also re'uires the AngularJS library to beprovided as well.

Project Directory Structure

The pro!ect is organized into the following directory structure to show you one method of organizing your code. ,ou do not have to follow thisdirectory structure however directory structure should be part of theoverall design of your pro!ects so that you can easily find the code that

 you are looking for.

Page 3: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 3/43

1 ./: 0ro!ect root that contains the base application files and supportingfolders.1 ./npm_modules: )reated when the #0$s listed above are installed inthe system.

1 ./controllers: )ontains the 4xpress route controllers that provide theinteraction between routes and changes to the $ongo%& database.1 ./models: )ontains the $ongoose model definitions for ob!ects in thedatabase.1 ./static: )ontains any static files that need to be sent such as )SS and

 AngularJS JavaScript and AngularJS partial templates.1 ./views: )ontains the "T$3 templates that will be rendered by 4JS.1 ../images: )ontains any images for the pro!ect. This is at a peer level tothe pro!ect so that the same images can be used by multiple pro!ects.

1 ../lib: )ontains the AngularJS libraries so that they can be loadedlocally my multiple pro!ects. In production you may want to use a )%#delivery address instead.

In addition to the directory structure the following code files areincluded. The following list is intended to give you an idea of thefunctionality of each file-

1 ./cart_init.js: Standalone initialization code for this example. It willcreate a single customer named customerA and add several products to

use in the example.1 ./cart_server.js: $ain application file that loads the necessarylibraries creates a connection to $ongo%& and starts the 4xpress server.1 ./cart_routes.js: %efines the routes for the 4xpress server.5unctionality that does not interact with the database is also handleddirectly in this file.1 ./controllers/customers_controller.js: %efines the functionality forthe routes that re'uire interaction with the $ongo%& database to getand update customer data such as cart shipping and billing information.

1 ./controllers/orders_controller.js: %efines the functionality for theroutes that re'uire interaction with the $ongo%& database to get theorder ob!ects.1 ./controllers/products_controller.js: %efines the functionality forthe routes that re'uire interaction with the $ongo%& database to get theone or all product ob!ects.

Page 4: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 4/43

1 ./models/cart_model.js- %efines the customer product order andsupporting models for the cart example.1 ./views/shopping.html: 0rovides the main shopping page for theapplication that will allow the user to view products and place them into

the cart.1 ./static/billing.html: This is an AngularJS partial that implementsthe billing information view.1 ./static/cart.html: This is an AngularJS partial that implements theshopping cart view.1 ./static/orders.html: This is an AngularJS partial that implements a

 view with a list of orders.1 ./static/products.html: This is an AngularJS partial that implementsa list of products view.1./static/product.html

: This is an AngularJS partial that implements a view for a single product with an add to cart link.1 ./static/review.html: This is an AngularJS partial that implements a

 view to allow the user to review the order before placing it.1 ./static/shipping.html: This is an AngularJS partial that implementsthe shipping information view.1 ./static/js/cart_app.js- 0rovides the AngularJS module andcontroller definitions to handle all of the shopping cart interaction

 between the AngularJS code and the webserver.1 ./static/css/cart_styles.css- 0rovides the )SS styling for the

 AngularJS "T$3 pages.

Defining the Custoer! Product and Orders "ode#s

 As always you should look at the ob!ect model needs as the first step inimplementing your applications. In this case the ob!ect of the exercise isto provide a shopping cart. To do so we will need a customer model as acontainer for the shopping cart. Also we will need products to place intothe shopping cart. To checkout we will need billing information and

shipping information and then once the order is placed we will need a way to store the order.

Therefore we need a model for the customer product order billing andshipping data to support the shopping cart. The following sectionsdiscuss the design of each of the model schemas implemented in thepro!ect. The schemas are all contained in a file name cart_model.js that

Page 5: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 5/43

implements all of the schemas. The first two lines and the final line ofthat file are as follows to load mongoose Schema-

67 var mongoose 8 re'uire9:mongoose:;6* Schema 8 mongoose.Schema<

The rest of the lines will be given in each section below as they aredescribed.

Defining the $ddress Schea

 /e begin by defining an address schema that will be generic so that itcan be used in both the shipping information and as part of the billinginformation. The code in 3isting *=.7 implements

theAddressSchema containing the standard address information. #otice thatthe following code is used to disable the _id property since we will notneed to look up addresses by id-

> ?id- false @

Listing 28.1. cart_model.js-AddressSchema e!ining a Schema !or Shi""ingand #illing Addresses

6 var AddressSchema 8 new Schema9>

6B name- String6C address- String6+ city- String6D state- String6= zip- String6E @ > ?id- false @;<76 mongoose.model9:Address: AddressSchema;<

Defining the %i##ing Schea

 /ith the AddressSchema defined we can now define the billing schema tokeep track of credit card information as well as billing information. Thecode in 3isting *=.* implements the BillingSchemacontaining standardcredit card data. #otice that the following implementationfor cardtype will re'uire that an entry of Visa MasterCard or Amex is used noother values are allowed-

Page 6: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 6/43

cardtype- > type- String enum- F:Gisa: :$aster)ard: :Amex:H @

 Also notice that the address field is assigned the AddressSchema ob!ect type.$ongoose re'uires that nesting schemas in this way be included in anarray. This is used in more than one place and you will see that throughthe example that the address will be access using address[0] to get the firstitem in the array.

Listing 28.2. cart_model.js-#illingSchema e!ining a Schema !or #illing $redit$ard and Address

77 var &illingSchema 8 new Schema9>7* cardtype- > type- String enum- F:Gisa: :$aster)ard: :Amex:H @7 name- String7B number- String7C expiremonth- #umber7+ expireyear- #umber7D address- FAddressSchemaH7= @ > ?id- false @;<7E mongoose.model9:&illing: &illingSchema;<

Defining the Product Schea

#ext we define the schema to store product information the product

model for this example is a print with aname imagefile description price and instock counter. 3isting *=. showsthe full definition of the ProductSchema.

Listing 28.3. cart_model.js-%rod&ctSchema e!ining a #asic %rod&ct Schema!or %rints

*6 var 0roductSchema 8 new Schema9>*7 name- String** imagefile- String

* description- String*B price- #umber*C instock- #umber*+ @;<*D mongoose.model9:0roduct: 0roductSchema;<

Defining the &uantity Schea

Page 7: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 7/43

5or orders and the shopping cart we can include the products in anarray however we also need the ability to store a 'uantity. ne methodof doing this is to define a 'uantity schema with 'uantity and productfields. 3isting *=.B implements the ProductQantitySchema that does !ust

that. #otice that since we are embedding the ProductSchema we include it asan array and through the example will access it using product[0].

Listing 28.4. cart_model.js-'&antit(Schema e!ining a #asic '&antit( Schema!or '&antit( o! %rod&cts in )rders and the $art

*D mongoose.model9:0roduct: 0roductSchema;<*= var 0roductuantitySchema 8 new Schema9>*E 'uantity- #umber6 product- F0roductSchemaH

7 @ > ?id- false @;<* mongoose.model9:0roductuantity: 0roductuantitySchema;<

Defining the Order Schea

#ext is the order schema that keeps track of the items ordered shippinginformation and billing information. 3isting *=.C implementsthe OrderSchema model that stores the necessary information about theorder. #otice that a Date type is assigned to the timestamp field to keeptrack of when the order was placed. Also the items field is an array

of QuantityShema sub documents.

Listing 28.5. cart_model.js-)rderSchema e!ining the )rder Schema to Storethe )rder *n!ormation

var rderSchema 8 new Schema9>B userid- StringC items- F0roductuantitySchemaH+ shipping- FAddressSchemaHD billing- F&illingSchemaH

= status- >type- String default- 0ending@E timestamp- > type- %ate default- %ate.now @B6 @;<B7 mongoose.model9:rder: rderSchema;<

Defining the Custoer Schea

Page 8: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 8/43

The final schema is the customer schema. 3isting *=.+ implementsthe CustomerSchema that contains a uni'ue userid field to identify thecustomer and associate orders with the customer. This field wouldnormally map to an authenticated session userid.

#otice that the shipping billing and cart are all nested schemas. Thatmakes is simple to define the model. ,ou will see that each of these will

 be accessed in the JavaScript usingthe shipping[0]billing[0] and cart[0] array indexing. #o cart ob!ectschema is necessary because it is inherently implemented by the arrayof ProductQuantitySchema subdocuments.

Listing 28.6. cart_model.js-$&stomerSchema e!ining the $&stomer Schemato Store the Shi""ing+ #illing and $art

B* var )ustomerSchema 8 new Schema9>B userid- > type- String uni'ue- true re'uired- true @BB shipping- FAddressSchemaHBC billing- F&illingSchemaHB+ cart- F0roductuantitySchemaHBD @;<B= mongoose.model9:)ustomer: )ustomerSchema;<

Creating the Shopping Cart Ser'er

 /ith the model defined you can begin implementing the shopping cartserver. The code in 3isting *=.Dimplements the 4xpress server for theshopping cart application. This code should be familiar to you. Itincludes the express and mongoose libraries and then connects to$ongo%& via $ongoose.

#otice that there is a require statement for the model definition to buildthe Schema ob!ect within $ongoose. Also the ./cart_routes files is included

to initialize the routes for the server before listening on port =6.Listing 28.7. cart_model.js *m"lementing the Sho""ing $art A""licationSer,er sing /"ress and $onnecting to 0ongo#

67 var express 8 re'uire9:express:;<6* var mongoose 8 re'uire9:mongoose:;<6 var db 8 mongoose.connect9:mongodb-KKlocalhostKcart:;<

Page 9: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 9/43

6B re'uire9:.KmodelsKcart?model.!s:;<6C var app 8 express9;<6+ app.engine9:.html: re'uire9:e!s:;.??express;<6D app.set9:views: ??dirname L :Kviews:;<

6= app.set9:view engine: :html:;<6E app.use9express.cookie0arser9;;<76 app.use9express.body0arser9;;<77 re'uire9:.Kcart?routes:;9app;<7* app.listen9=6;<

(p#eenting )outes to Support Product! Cart and Order )e*uests

 As part of the 4xpress server configuration the ./cart_routes.js file shownin 3isting *=.D was loaded. The code in 3isting *=.= provides the routes

necessary to get the customer product and order ob!ects. They alsoprovide routes to add orders to the database and update the customershipping billing and cart information.

3ines +ME implement the static routes to support getting the AngularJS)SS JavaScript images and AngularJS template partials used in thisexample. The images and AngularJS lib folders are located in a siblingdirectory to the pro!ect. The other static files are in the ./static folderinside the pro!ect.

#otice that when the user access the root location of / for the site thatthe shopping.html template is rendered on line 77. The remaining routes onlines 7M7E all involve interaction with the $ongo%& database and will

 be handled in the controller route handlers described in the next section.

Listing 28.8. cart_ro&tes.js *m"lementing the o&tes !or Sho""ing $art ee&ests !rom the $lient

67 var express 8 re'uire9:express:;<

6* module.exports 8 function9app; >6 var customers 8 re'uire9:.KcontrollersKcustomers?controller:;<6B var products 8 re'uire9:.KcontrollersKproducts?controller:;<6C var orders 8 re'uire9:.KcontrollersKorders?controller:;<6+ app.use9:Kstatic: express.static9 :.Kstatic:;;.6D use9:Kimages: express.static9 :..Kimages:;;.6= use9:Klib: express.static9 :..Klib:;

Page 10: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 10/43

6E ;<76 app.get9:K: function9re' res;>77 res.render9:shopping:;<7* @;<

7 app.get9:KproductsKget: products.get0roducts;<7B app.get9:KordersKget: orders.getrders;<7C app.post9:KordersKadd: orders.addrder;<7+ app.get9:KcustomersKget: customers.get)ustomer;<7D app.post9:KcustomersKupdateKshipping: customers.updateShipping;<7= app.post9:KcustomersKupdateKbilling: customers.update&illing;<7E app.post9:KcustomersKupdateKcart: customers.update)art;<*6 @

(p#eenting the "ode# %ased Contro##er )outes

In addition to the standard route implementation you also need toimplement route handling that interact with the database. These routehandlers are broken out of the standard cart_route.js file and into theirown files based on model to keep the code clean and ensure a gooddivision of responsibilities.

The following sections cover the implementation of the model specificcontrollers for the CustomerOrder and Product models.

(p#eenting the Product "ode# Contro##er

The code in 3isting *=.E implements the route handling code forthe Product model. There are only two routes. The getProduct() route findsa single product based on the productId included in the 'uery.The getProducts() route finds all products. If successful the product or allproducts are returned to the client as JS# strings. If the re'uests failthen a B6B error is returned.

Listing 28.. "rod&cts_controller.js *m"lementing the et %rod&ct and et%rod&cts o&tes !or the /"ress Ser,er

67 var mongoose 8 re'uire9:mongoose:;6* 0roduct 8 mongoose.model9:0roduct:;<6 exports.get0roduct 8 function9re' res; >6B 0roduct.findne9> ?id- re'.'uery.productId @;

Page 11: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 11/43

6C .exec9function9err product; >6+ if 9Nproduct;>6D res.!son9B6B >msg- :0hoto #ot 5ound.:@;<6= @ else >

6E res.!son9product;<76 @77 @;<7* @<7 exports.get0roducts 8 function9re' res; >7B 0roduct.find9;7C .exec9function9err products; >7+ if 9Nproducts;>7D res.!son9B6B >msg- :0roducts #ot 5ound.:@;<7= @ else >7E res.!son9products;<*6 @*7 @;<** @<

(p#eenting the Order "ode# Contro##er

The code in 3isting *=.76 implements the route handling code forthe Order model. There are three routes. The getOrder() route finds a single

order based on the orderId included in the 'uery. ThegetOrders() routefinds all orders that belong to the current user. In the case of the exampletheuserid of customerA is hard coded. If successful the order or all of thiscustomerOs orders are returned to the client as JS# strings. If there'uests fail then a B6B error is returned.

The addOrder() route handler builds a new Order ob!ect by gettingthe updatedShippingupdatedBilling and orderItems parameters fromthe POST re'uest. If the order saves successfully then the cart field in thecustomer ob!ect is reset to empty using the following code and a success

is returned otherwise a C66 or B6B error is returned.

D )ustomer.update9> userid- :customerA: @= >Pset->cart-FH@@;

Page 12: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 12/43

Listing 28.1. orders_controller.js *m"lementing the et )rders9 and Add)rder o&tes !or the /"ress Ser,er

67 var mongoose 8 re'uire9:mongoose:;6* )ustomer 8 mongoose.model9:)ustomer:;

6 rder 8 mongoose.model9:rder:;6B Address 8 mongoose.model9:Address:;6C &illing 8 mongoose.model9:&illing:;<6+ exports.getrder 8 function9re' res; >6D rder.findne9> ?id- re'.'uery.orderId @;6= .exec9function9err order; >6E if 9Norder;>76 res.!son9B6B >msg- :rder #ot 5ound.:@;<77 @ else >

7* res.!son9order;<7 @7B @;<7C @<7+ exports.getrders 8 function9re' res; >7D rder.find9>userid- :customerA:@;7= .exec9function9err orders; >7E if 9Norders;>*6 res.!son9B6B >msg- :rders #ot 5ound.:@;<

*7 @ else >** res.!son9orders;<* @*B @;<*C @<*+ exports.addrder 8 function9re' res;>*D var orderShipping 8 new Address9re'.body.updatedShipping;<*= var order&illing 8 new &illing9re'.body.updated&illing;<*E var orderItems 8 re'.body.orderItems<6 var newrder 8 new rder9>userid- :customerA:

7 items- orderItems shipping- orderShipping* billing- order&illing@;< newrder.save9function9err results;>B if9err;>C res.!son9C66 5ailed to save rder.;<+ @ else >

Page 13: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 13/43

D )ustomer.update9> userid- :customerA: @= >Pset->cart-FH@@;E .exec9function9err results;>B6 if 9err QQ results R 7;>

B7 res.!son9B6B >msg- :5ailed to update )art.:@;<B* @ else >B res.!son9>msg- rder Saved.@;<BB @BC @;<B+ @BD @;<B= ;<

(p#eenting the Custoer "ode# Contro##er

The code in 3isting *=.77 implements the route handling code forthe Customer model. There are four routes.

The getCustomer() route finds a customer order based on the hardcoded customerA value. If successful the customer ob!ect is returned to theclient as JS# strings. If the re'uests fails then a B6B error is returned.

The updateShipping() route will create a new Address ob!ect fromthe updatedShippingparameter in the POST re'uest and then usean update() method to update the customer ob!ect with the new shippingdata. If successful a success message is returned if it fails then a B6Berror is returned.

The updateBilling() route will create a new &illing ob!ect fromthe updatedBilling parameter in the POST re'uest and then use an update9;method to update the customer ob!ect with the new billing data. Ifsuccessful a success message is returned if it fails then a B6B error isreturned.

The updateCart() route will use the update() method to update the cart fieldof the customer with the updatedCart ob!ect sent in the POST re'uest. Ifsuccessful a success message is returned if it fails then a B6B error isreturned.

Page 14: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 14/43

Listing 28.11. c&stomers_controller.js *m"lementing the $&stomer et and"date o&tes !or the /"ress Ser,er

67 var mongoose 8 re'uire9:mongoose:;6* )ustomer 8 mongoose.model9:)ustomer:;

6 Address 8 mongoose.model9:Address:;6B &illing 8 mongoose.model9:&illing:;<6C exports.get)ustomer 8 function9re' res; >6+ )ustomer.findne9> userid- :customerA: @;6D .exec9function9err customer; >6= if 9Ncustomer;>6E res.!son9B6B >msg- :)ustomer #ot 5ound.:@;<76 @ else >77 res.!son9customer;<

7* @7 @;<7B @<7C exports.updateShipping 8 function9re' res;>7+ var newShipping 8 new Address9re'.body.updatedShipping;<7D )ustomer.update9> userid- :customerA: @7= >Pset->shipping-FnewShipping.tob!ect9;H@@;7E .exec9function9err results;>*6 if 9err QQ results R 7;>

*7 res.!son9B6B >msg- :5ailed to update Shipping.:@;<** @ else >* res.!son9>msg- )ustomer Shipping 2pdated@;<*B @*C @;<*+ @<*D exports.update&illing 8 function9re' res;>*= KK This is where you could verify the credit card information*E KK and halt the checkout if it is invalid.6 var new&illing 8 new &illing9re'.body.updated&illing;<

7 )ustomer.update9> userid- :customerA: @* >Pset->billing-Fnew&illing.tob!ect9;H@@; .exec9function9err results;>B if 9err QQ results R 7;>C res.!son9B6B >msg- :5ailed to update &illing.:@;<+ @ else >

Page 15: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 15/43

D res.!son9>msg- )ustomer &illing 2pdated@;<= @E @;<B6 @<

B7 exports.update)art 8 function9re' res;>B* )ustomer.update9> userid- :customerA: @B >Pset->cart-re'.body.updated)art@@;BB .exec9function9err results;>BC if 9err QQ results R 7;>B+ res.!son9B6B >msg- :5ailed to update )art.:@;<BD @ else >B= res.!son9>msg- )ustomer )art 2pdated@;<BE @C6 @;<C7 @<

(p#eenting Shopping Cart and Chec+out ,iews

#ow that the routes are setup and configured you are ready toimplement the views that are rendered by the routes and AngularJStemplates. The following sections discuss the main shopping.html viewrendered by 4JS as well as the various partial views that make upthe cart shipping billingreview and orders pages.

(p#eenting the Shopping ,iew

The shopping view shown in 3isting *=.76 is the main view for theshopping application. In fact the user will never actually leave this pageonly the content will change using the partial views described in thefollowing sections.

The header of the view registers the <html ng-app="myApp"> element with the AngularJS myAppapplication and loads the cart_styles.css file.

The <body> element initializes the AngularJS ng-

controller="shoppingControler" to provide the functionality to interact withthe products shopping cart checkout and orders.

The page content changing works using the following ng-include directivethat maps to$scope.content. The content variable in the scope can then beset to which every template file on the server that you want.

Page 16: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 16/43

Rdiv ngMinclude8contentRKdiv

 An example of this is shown in the orders and shopping cart clickablelinks shown below that callsetConent() with the name of the template fileto load.

Rspan class8orders  ngMclick8set)ontent9:orders.html:;rdersRKspanRspan id8cart3ink ngMclick8set)ontent9:cart.html:; >>customer.cart.length@@ items  Rimg src8KimagesKcart.png KRKspan

 Also notice that the number of items in the cart is taken directly from the

scope variablecustomer.cart.length. The customer ob!ect in the scope isdownloaded directly from the web server when the controller isinitialized. 5igure *=.7 shows the full rendered shopping.html page.

Listing 28.12. sho""ing.html *m"lementing the 0ain Sho""ing %age Ang&larS;em"late $ode

67 RNdoctype html6* Rhtml ngMapp8myApp6 Rhead

6B RtitleShopping )artRKtitle6C Rlink rel8stylesheet type8textKcss6+ href8KstaticKcssKcart?styles.css K6D RKhead6= Rbody6E Rdiv ngMcontroller8shopping)ontroller76 Rdiv id8banner77 Rdiv id8title$y StoreRKdiv7* Rdiv id8bar

7 Rspan class8orders7B ngMclick8set)ontent9:orders.html:;rdersRKspan7C Rspan id8cart3ink ngMclick8set)ontent9:cart.html:;7+ >>customer.cart.length@@ items7D Rimg src8KimagesKcart.png K7= RKspan7E RKdiv

Page 17: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 17/43

*6 RKdiv*7 Rdiv id8main** Rdiv ngMinclude8contentRKdiv* RKdiv

*B RKdiv*C Rscript src8KlibKangularKangular.!sRKscript*+ Rscript src8KstaticK!sKcart?app.!sRKscript*D RKbody*= RKhtml

<ig&re 28.1. endered sho""ing "age =ith the sho""ing cart lin> and orderslin> as =ell as a list o! "rints to sho" !or.

(p#eenting the Products ,iew

#ext we implement the products view to provide the user with a list of

products to choose from. In this example the shopping page is very basiconly a single page with a list of prints to buy. This is basic but it isenough to demonstrate the implementation of the shopping cart and itkeeps the code simple.

The code in 3isting *=.7* is an AngularJS partial that is loaded into the view when the$scope.content is set to products.html. The code uses an ng-

repeat on the products that are initialized when the shoppingController isinitialized. #otice that the product information is displayed on the pageusing expressions such as {{product.name}}.

 Also notice that when the user clicks on the <img> element thatthe setProduct() function is called in the controller. That function will setthe current $scope.product value and change the$scope.content value toproduct.html. 5igure *=.* shows the rendered products view.

Page 18: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 18/43

Listing 28.13. "rod&cts.html *m"lementing the %rod&ct Listing ;em"late%artial

67 Rdiv id8products)ontainer6* Rdiv class8listItem ngMrepeat8product in products

6 Rimg class8listImg ngMclick8set0roduct9product.?id;6B ngMsrc8..KimagesK>>product.imagefile@@ K6C Rspan class8prod#ame>>product.name@@RKspan6+ Rspan class8price>>product.priceQcurrency@@RKspan6D RKdiv6= RKdiv

<ig&re 28.2. %rod&ct listing ,ie= sho=ing "rints a,ailale.

(p#eenting the Product ,iew

 /hen the user clicks on the image in the products list the product page view is rendered. 3isting *=.7Bshows the AngularJS code used for theproduct page view. #otice that the product information is displayedusing AngularJS expressions that are accessing he $scope.product value.The add to cart button sends the product._id to the addToCart() function inthe controller which will add the print to the cart. 5igure *=. shows therendered product view that showsthe image namedescription quantity and price as well as the add to cart

 button.

Listing 28.14. "rod&ct.html *m"lementing the %rod&ct etails ;em"late %artial =ith Add to $art #&tton

67 Rdiv id8products)ontainer6* Rdiv class8listItem ngMrepeat8product in products6 Rimg class8listImg ngMclick8set0roduct9product.?id;6B ngMsrc8..KimagesK>>product.imagefile@@ K

Page 19: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 19/43

6C Rspan class8prod#ame>>product.name@@RKspan6+ Rspan class8price>>product.priceQcurrency@@RKspan6D RKdiv6= RKdiv

<ig&re 28.3. %rod&ct details ,ie= sho=ing descri"tion+ a,ailale and add tocart &tton.

(p#eenting the Cart ,iew

nce the user clicks on the add to cart button the item is added to thecart and the view is changed to the cart view. The cart view shownin 3isting *=.7B provides a list of products that are currently existing inthe cart a price total and buttons to check out or go back shopping.

The following code implements a delete link in the cart to remove the

item. It calls a functiondeleteFromCart() located in the controller an passesthe product._id to identify which item to delete.

Rspan class8delete  ngMclick8delete5rom)art9product.?id;emoveRKspan

 Also a 'uantity field is provided that links directly tothe item.quantity element where item comes from the ngMrepeat ofthe customer.shopping cart array.

The shipping value and total value are calculated by a controller functionthat is linked by the following expression code. The Qcurrency filter is usedto format the values of price shipping and total-

Rspan class8price>>cartTotal9;Qcurrency@@RKspan

Page 20: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 20/43

The cool part about AngularJS is that because the quantity fields arelinked directly to the scope as you change them the shipping and total

 values change as well. 5igure *=.B shows the rendered shopping cart view.

Listing 28.15. cart.html *m"lementing the Sho""ing $art ;em"late %artial

67 Rdiv id8carts)ontainer6* Rdiv class8listItem ngMrepeat8item in customer.cart6 ngMinit8product8item.productF6H6B Rimg class8listImg ngMclick8set0roduct9product.?id;6C ngMsrc8..KimagesK>>product.imagefile@@ K6+ Rspan class8prod#ame>>product.name@@RKspan6D Rspan

6= Rspan class8price>>product.priceQcurrency@@RKspan6E Rinput class8'uantity type8text ngMmodel8item.'uantity K76 Rlabel class8'uantityuantityRKlabel77 Rspan class8delete7* ngMclick8delete5rom)art9product.?id;emoveRKspan7 RKspan7B RKdiv7C Rhr7+ Rdiv

7D RspanShippingRKspan7= Rspan class8price>>shippingQcurrency@@RKspan7E RKdiv*6 Rhr*7 Rdiv** RspanTotalRKspan* Rspan class8price>>cartTotal9;Qcurrency@@RKspan*B RKdiv*C Rhr*+ Rdiv*D Rspan class8button ngMclick8checkout9;*= ngMhide8customer.cart.length886*E )heckout6 RKspan7 Rspan class8button ngMclick8set)ontent9:products.html:;* )ontinue Shopping

Page 21: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 21/43

RKspanB RKdivC RKdiv

<ig&re 28.4. Sho""ing cart ,ie= allo=ing the c&stomer to change &antit(+

remo,e items and chec>o&t.

(p#eenting the Shipping ,iew

 /hen the user clicks on the checkout button in the shopping cart they will be directed to the shipping view that allows them to enter shippinginformation. The shipping view shown in 3isting *=.7+ provides a seriesof input fields to input the shipping information.

The shipping template code is very straightforward. There are a series oftext inputs wit labels for each shipping field value. The fields are linked

to the customer.shipping[0] ob!ect in the scope model using the ng-model directive. That way when the user changes the field the scope isautomatically changed. ,ou will see that this is very useful when sendingcustomer changes back to the database. /hen the user clicks on the)ontinue to &illing button the shipping data will be updated on theserver as well and they will be taken to the billing view. The renderedshipping view is shown in 5igure *=.C.

Listing 28.16. shi""ing.html *m"lementing the Shi""ing ;em"late %artial

67 Rdiv id8shipping)ontainer6* Rh*Ship To-RKh*6 Rlabel#ameRKlabel6B Rinput type8text ngMmodel8customer.shippingF6H.name KRbr6C RlabelAddressRKlabel6+ Rinput type8text ngMmodel8customer.shippingF6H.addressKRbr

Page 22: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 22/43

6D Rlabel)ityRKlabel6= Rinput type8text ngMmodel8customer.shippingF6H.city KRbr6E RlabelStateRKlabel76 Rinput type8text ngMmodel8customer.shippingF6H.state KRbr

77 RlabelUipcodeRKlabel7* Rinput type8text ngMmodel8customer.shippingF6H.zip K7 Rhr7B Rdiv7C Rspan class8button ngMclick8setShipping9;7+ )ontinue to &illing7D RKspan7= Rspan class8button ngMclick8set)ontent9:products.html:;7E )ontinue Shopping*6 RKspan*7 RKdiv** RKdiv

<ig&re 28.5. Shi""ing ,ie= allo=ing the &ser to enter in the address to shi" the"a(ment to.

(p#eenting the %i##ing ,iew

 /hen the user clicks on the )ontinue to &illing button in the shipping view they will be directed to the billing view that allows them to billinginformation. The billing view shown in 3isting *=.7+ provides a series of 

input fields to input the billing information.

The billing template code is similar to the shipping template with theaddition of a few new fields. The card radio buttons to select the creditcard are bound to the customer.billing[0].cardtype value in the scope. /hen

 you change the radio button selection the model is also changed.

Page 23: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 23/43

The values for the <select> dropdown options come from simple arraysdefined in the scope and are bound to the customer.billing[0] data as well.5or example the following lines use an array of number named monthsin the scope and binds the <select> value to

thecustomer.billing[0].expiremonth value in the scope-

Rselect ngMmodel8customer.billingF6H.expiremonth  ngMoptions8m for m in monthsRKselect

ne other thing to note is that the ))G value is passed tothe verifyBilling(ccv) function when verifying the credit card. The ))Gnumber is not supposed to be stored locally on the customer site so it iskept separate here and passed as itsO own parameter. The rendered

 billing view is shown in 5igure *=.+.

Listing 28.17. illing.html *m"lementing the #illing ;em"late %artial

67 Rdiv id8shipping)ontainer6* Rh*)ard Info- RKh*6 Rlabel)ardRKlabel6B Rinput type8radio ngMmodel8customer.billingF6H.cardtype6C value8Gisa Gisa6+ Rinput type8radio ngMmodel8customer.billingF6H.cardtype6D value8Amex Amex

6= Rinput type8radio ngMmodel8customer.billingF6H.cardtype6E value8$aster)ard $aster)ard76 RbrRlabel#ame on )ardRKlabel77 Rinput type8text ngMmodel8customer.billingF6H.name K7* RbrRlabel)ard #umberRKlabel7 Rinput type8text ngMmodel8customer.billingF6H.number K7B RbrRlabel4xpiresRKlabel7C Rselect ngMmodel8customer.billingF6H.expiremonth7+ ngMoptions8m for m in monthsRKselect

7D Rselect ngMmodel8customer.billingF6H.expireyear7= ngMoptions8m for m in yearsRKselect7E Rlabel)ard ))GRKlabel*6 Rinput class8security type8text ngMmodel8ccv K*7 Rh*&illing Address-RKh*** Rlabel#ameRKlabel* Rinput type8text

Page 24: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 24/43

*B ngMmodel8customer.billingF6H.addressF6H.name K*C RbrRlabelAddressRKlabel*+ Rinput type8text*D ngMmodel8customer.billingF6H.addressF6H.address K

*= RbrRlabel)ityRKlabel*E Rinput type8text6 ngMmodel8customer.billingF6H.addressF6H.city K7 RbrRlabelStateRKlabel* Rinput type8text ngMmodel8customer.billingF6H.addressF6H.state KB RbrRlabelUipcodeRKlabelC Rinput type8text+ ngMmodel8customer.billingF6H.addressF6H.zip KD Rhr= RdivE Rspan class8button ngMclick8verify&illing9ccv;B6 Gerify &illingB7 RKspanB* Rspan class8button ngMclick8set)ontent9:products.html:;B )ontinue ShoppingBB RKspanBC RKdivB+ RKdiv

<ig&re 28.6. #illing in!ormation ,ie= allo=ing the &ser to enter in a credit cardand illing address.

(p#eenting the )e'iew ,iew

 /hen the user clicks on the Gerify &illing button in the billing view they will be taken to the review view so they can review the order along withshipping and billing information. The review view shown in 3isting

Page 25: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 25/43

*=.7D shows the ordered items with totals as well as the shipping and billing information.5igure *=.D shows the rendered review view.

<ig&re 28.7. e,ie= ,ie= allo=ing the c&stomer to re,ie= their "&rchase.

#otice that all the information displayed is still coming from the

customer ob!ect inside the scope. The shipping information comesfrom customer.shipping[0] the billing information comesfromcustomer.billing[0] and the product list comes from customer.cart.

 /hen the customer clicks on the $ake 0urchase button this information will be sent to the webserver and a new order ob!ect will be created. The view will then be changed to the order view.

Listing 28.18. re,ie=.html *m"lementing the )rder e,ie= ;em"late %artial

67 Rdiv id8review)ontainer6* Rdiv class8listItem ngMrepeat8item in customer.cart6 ngMinit8product8item.productF6H6B Rimg class8listImg ngMclick8set0roduct9product.?id;6C ngMsrc8..KimagesK>>product.imagefile@@ K6+ Rspan class8prod#ame>>product.name@@RKspan6D Rspan 6= Rspan class8price>>product.priceQcurrency@@RKspan6E Rlabel class8'uantity>>item.'uantity@@RKlabel76 Rlabel class8'uantityuantityRKlabel77 RKspan7* RKdivRhr7 Rdiv7B RspanShippingRKspan7C Rspan class8price>>shippingQcurrency@@RKspan7+ RKdivRhr

Page 26: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 26/43

7D Rdiv7= RspanTotalRKspan7E Rspan class8price>>cartTotal9;Qcurrency@@RKspan*6 RKdivRhr

*7 Rdiv** Rdiv class8review* Shipping-Rbr*B >>customer.shippingF6H.name@@Rbr*C >>customer.shippingF6H.address@@Rbr*+ >>customer.shippingF6H.city@@*D >>customer.shippingF6H.state@@*= >>customer.shippingF6H.zip@@Rbr*E RKdiv6 Rdiv class8review7 &illing-Rbr* >>customer.billingF6H.cardtype@@ ending in >>customer.billingF6H.number.slice9MCM7;@@RbrB >>customer.billingF6H.addressF6H.name@@RbrC >>customer.billingF6H.addressF6H.address@@Rbr+ >>customer.billingF6H.addressF6H.city@@D >>customer.billingF6H.addressF6H.state@@= >>customer.billingF6H.addressF6H.zip@@RbrE RKdiv

B6 RKdivB7 RdivB* Rspan class8button ngMclick8make0urchase9;B $ake 0urchaseBB RKspanBC Rspan class8button ngMclick8set)ontent9:products.html:;B+ )ontinue ShoppingBD RKspanB= RKdiv

BE RKdiv

(p#eenting the Orders ,iew

 /hen the order is complete the user will be taken to the orders view tosee their completed purchases. This is only one method you could addanother page to display the completed order or you could !ust send the

Page 27: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 27/43

user back to the shopping page. "owever for the purpose of !ust givingan example this method seems as good as any.

The orders view shown in 3isting *=.7E displays a list of orders that thiscustomer has completed. The list comes from an ng-repeat directive onthe $scope.orders value. /ithin the ng-repeatiteration the date placedstatus and items bought are listed as shown in 5igure *=.=.

Listing 28.1. orders.html *m"lementing the )rders ?ie= ;em"late %artial

67 Rdiv id8review)ontainer6* Rdiv class8listItem ngMrepeat8order in orders6 Rp class8itemTitlerder V>>PindexL7@@RKp6B Rp class8prod%esc0laced >>order.timestampQdate@@RKp

6C Rp class8status>>order.status@@RKp6+ Rdiv class8listItem ngMrepeat8item in order.items6D ngMinit8product8item.productF6H6= Rimg class8listImg ngMclick8set0roduct9product.?id;6E ngMsrc8..KimagesK>>product.imagefile@@ K76 Rspan class8prod#ame>>product.name@@RKspan77 Rspan 7* Rspan class8price>>product.priceQcurrency@@RKspan7 Rlabel class8'uantity>>item.'uantity@@RKlabel7B Rlabel class8'uantityuantityRKlabel7C RKspan7+ RKdiv7D RKdiv7= Rdiv7E Rspan class8button ngMclick8set)ontent9:products.html:;*6 )ontinue Shopping*7 RKspan** RKdiv* RKdiv

Page 28: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 28/43

<ig&re 28.8. List o! orders that ha,e een "laced ( this c&stomer.

$dding CSS to Sty#i-e the ,iews

3isting *=.*6 shows the )SS code that is used to style the elements in theshopping cart so that you can see why things look and act the way theydo. The )SS is condensed as much as possible to make it fit into the

 book. Also the titles buttons and such are implemented large to make itdisplay better in the bookOs figures.

Listing 28.2. st(les.css *m"lementing the $SS St(les !or the ?ie= @;0L <iles

67 p>margin-6@6* label >width-766px< display-inlineMblock< textMalign-right< @6 inputFtype8textH> border- *px ridge blue< padding-px<6B borderMradius-Cpx< width-B66px< @

6C Vbanner> borderMbottom- *px blue ridge< height-766px @6+ Vtitle > textMalign-center< backgroundMcolor-Va6d6ff<6D font-italic bold B=pxK+6px Weorgia serif< borderMradius- Cpx @6= Vbar > backgroundMcolor-Va6d6ff< @6E Vcart3ink > float-right< textMalign-right< cursor-pointer @76 Vcart3ink img > height-*Cpx< @77 Vmain >clear-both<@7* .listItem>borderMbottom- 7px solid black< clear-both<7 marginMtop-76px @7B .listImg > height-C6px< verticalMalign-top @7C .fullImg > width-66px< verticalMalign-top @7+ .prod#ame >font- bold 7+pxK*6px Arial SansMserif< @7D .price> float-right< color-red< width-DCpx< textMalign-right<7= display-inlineMblock@7E .prodInfo> display-inlineMblock< @*6 .itemTitle >font- bold *pxKB6px Arial SansMserif< @

Page 29: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 29/43

*7 .full0rice > color-red< font- bold *6pxK*Bpx Arial SansMserif<** textMalign-right@* .status >color-green< font- bold 7BpxK7=px Arial SansMserif<@*B .prod%esc > fontMstyle- italic< @

*C .button*+ .cart&utton> font- 7=pxK*Bpx Arial SansMserif< borderMradius- 76px<*D padding-76px< marginMtop-Cpx< cursor- pointer< width-7D6px<*= backgroundMimage- MwebkitMlinearMgradient9top V55))++V5555EE;<*E textMalign-center@6 .cart&utton img > height-*6px< float-right@7 .button> display-inlineMblock< margin-76px<@* input.'uantity > display-inlineMblock< float-right< width-6px< @ label.'uantity > display-inlineMblock< float-right< width-+6px<B marginMright-=px< @C span.orders+ span.delete > cursor-pointer< display-inlineMblock< float-right<D backgroundMcolor-V55C=C=< borderMradius- =px< textMalign-center<= font- bold 7pxK*6px Arial SansMserif<E marginMright-*6px< width-=6px< @B6 span.orders> marginMtop-Cpx< marginMright-76px<B7 backgroundMimage- MwebkitMlinearMgradient9top V55))++V5555EE;<@

B* input.security > width-6px @B div.review> display-inlineMblock< width-BCX< verticalMalign-top< @

(p#eenting the $ngu#arS "odu#e and Contro##er to support

Shopping Cart ,iews

 /ith the views finished you need to implement the AngularJS controllercode that will support them. The views need the ability to get thecustomer products and orders documents from the webserver. They also

need the ability to update the customer shipping billing and cart as wellas the ability to process new orders.

In the shopping cart example everything was built into a single moduleand controller. The controller code is a bit long for a single section in the

 book so the following sections break down the various components of

Page 30: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 30/43

the controller code so they can be described in smaller code chunks. Thefull Angular JS code in for the controller is shown in 3isting *=.*=.

(nitia#i-ing the Shopping Scope

The first step in implementing the shoppingController is to initialize thescope values that we need. The code in 3isting *=.*7 initializes theshopping scope. The $scope.months and$scope.years arrays are used topopulate the credit card form. The Pscope.content determines which

 AngularJS partial is rendered in the view. It is initializedto products.html so the user can begin shopping.

#ext there are three Phttp re'uests that get the products customer andorders and use the results to set

the $scope.products $scope.product $scope.customer and $scope.orders ob!ectsthat are utilized in the AngularJS views.

Listing 28.21. cart_a"".js-initialie *m"lementing the $SS St(les !or the ?ie=@;0L <iles

66B Pscope.months 8 F7*BC+D=E76777*H<66C Pscope.years 8 F*67B*67C*67+*67D*67=*67E*6*6H<66+ Pscope.content 8 :KstaticKproducts.html:<66D Phttp.get9:KproductsKget:;

66= .success9function9data status headers config; >66E Pscope.products 8 data<676 Pscope.product 8 dataF6H<677 @;67* .error9function9data status headers config; >67 Pscope.products 8 FH<67B @;<67C Phttp.get9:KcustomersKget:;67+ .success9function9data status headers config; >

67D Pscope.customer 8 data<67= @;67E .error9function9data status headers config; >6*6 Pscope.customer 8 FH<6*7 @;<6** Phttp.get9:KordersKget:;6* .success9function9data status headers config; >

Page 31: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 31/43

6*B Pscope.orders 8 data<6*C @;6*+ .error9function9data status headers config; >6*D Pscope.orders 8 FH<

6*= @;<(p#eenting /e#per 0unctions

#ext we add the helper functions shown in 3isting *=.** that providefunctionality for the AngularJS templates. The setContent() function setsthe $scope.content value effectively changing the view.The setProduct() function is called when a user clicks on a print image andsets the$scope.product used in the product view. The cartTotal() function

 will iterate through the products in the users cart and update

the $scope.shipping and return a total used in the cart and review views.

Listing 28.22. cart_a"".js-hel"ers *m"lementing the $SS St(les !or the ?ie=@;0L <iles

6*E Pscope.set)ontent 8 function9filename;>66 Pscope.content 8 :KstaticK:L filename<67 @<6* Pscope.set0roduct 8 function9productId;>6 Pscope.product 8 this.product<

6B Pscope.content 8 :KstaticKproduct.html:<6C @<6+ Pscope.cartTotal 8 function9;>6D var total 8 6<6= for9var i86< iRPscope.customer.cart.length< iLL;>6E var item 8 Pscope.customer.cartFiH<6B6 total L8 item.'uantity Y item.productF6H.price<6B7 @6B* Pscope.shipping 8 totalY.6C<

6B return totalLPscope.shipping<6BB @<

$dding (tes to the Cart

The addToCart() function shown in 3isting *=.* is called from thetemplate when the user clicks on the add to cart button. The first thing it

Page 32: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 32/43

does is iterate through the items in the customer.cartand if it finds theitem is there it increments the 'uantity otherwise it adds the item tothecustomer.cart array with a 'uantity of 7.

nce the $scope.customer is updated an $http POST is called tothe/customers/update/cart route to update the cart. That way the cart ispersistent and will be there even if you user closes the browser ornavigates away. n success the view is switched to cart.html. n failurean alert window is displayed.

Listing 28.23. cart_a"".js-add;o$art st(les.css *m"lementing the $SS St(les!or the ?ie= @;0L <iles

6BC Pscope.addTo)art 8 function9productId;>6B+ var found 8 false<6BD for9var i86< iRPscope.customer.cart.length< iLL;>6B= var item 8 Pscope.customer.cartFiH<6BE if 9item.productF6H.?id 88 productId;>6C6 item.'uantity L8 7<6C7 found 8 true<6C* @6C @6CB if 9Nfound;>6CC Pscope.customer.cart.push9>'uantity- 7

6C+ product- Fthis.productH@;<6CD @6C= Phttp.post9:KcustomersKupdateKcart:6CE > updated)art- Pscope.customer.cart @;6+6 .success9function9data status headers config; >6+7 Pscope.content 8 :KstaticKcart.html:<6+* @;6+ .error9function9data status headers config; >6+B Pwindow.alert9data;<

6+C @;<6++ @<

De#eting (tes fro the Cart

The deleteFromCart() function shown in 3isting *=.*B is called from thecart template when the user clicks on the remove button. The first thing

Page 33: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 33/43

it does is iterate through the items in thecustomer.cart and if it finds theitem it uses the array.slice(index,1) method to delete it from the array.

nce the item is removed from $scope.customer.cart an $http POST is calledto the/customers/update/cart route to update the cart. That way the cart ispersistent and will be there even if you user closes the browser ornavigates away. n success the view is switched to cart.html. n failurean alert window is displayed.

Listing 28.24. cart_a"".js-delete<rom$art *m"lementing the $SS St(les !or the ?ie= @;0L <iles

6+D Pscope.delete5rom)art 8 function9productId;>6+= for9var i86< iRPscope.customer.cart.length< iLL;>6+E var item 8 Pscope.customer.cartFiH<6D6 if 9item.productF6H.?id 88 productId;>6D7 Pscope.customer.cart.splice9i7;<6D* break<6D @6DB @6DC Phttp.post9:KcustomersKupdateKcart:6D+ > updated)art- Pscope.customer.cart @;6DD .success9function9data status headers config; >6D= Pscope.content 8 :KstaticKcart.html:<

6DE @;6=6 .error9function9data status headers config; >6=7 Pwindow.alert9data;<6=* @;<6= @<

Chec+ing Out

The checkout() function shown in 3isting *=.*C is called when the userclicks on the checkout button in the cart view. This illustrates how useful

 AngularJS data binding really is. Since the customer information isalways kept up to date all that is necessary is to send an $http

POST re'uest with the parameter {updatedCart:$scope.customer.cart} toupdate the cart.

Page 34: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 34/43

The cart is updated to ensure that any 'uantity changes made in the cartpage will also be persistent later on if the user backs out of the purchase.If the re'uest is successful then the view is switched toshipping.html.

Listing 28.25. cart_a"".js-chec>o&t *m"lementing the $SS St(les !or the ?ie=

@;0L <iles

6=B Pscope.checkout 8 function9;>6=C Phttp.post9:KcustomersKupdateKcart:6=+ > updated)art- Pscope.customer.cart @;6=D .success9function9data status headers config; >6== Pscope.content 8 :KstaticKshipping.html:<6=E @;6E6 .error9function9data status headers config; >

6E7 Pwindow.alert9data;<6E* @;<6E @<

Setting Shipping (nforation

The setShipping() function shown in 3isting *=.*+ is called when theuser clicks on the continue to billing button in the cart view. Theshipping information needs to be updated in the database to ensure thatit is persistent when the customer leaves the website. An $http

POST method is called to the /customers/update/shipping route. The 0STincludes the parameter{updatedShipping:$scope.customer.shipping[0]}  in the

 body. If the re'uest is successful then the view is switched to billing.html.therwise an alert is displayed.

Listing 28.26. cart_a"".js-setShi""ing *m"lementing the $SS St(les !or the ?ie= @;0L <iles

6EB Pscope.setShipping 8 function9;>6EC Phttp.post9:KcustomersKupdateKshipping:

6E+ > updatedShipping- Pscope.customer.shippingF6H @;6ED .success9function9data status headers config; >6E= Pscope.content 8 :KstaticKbilling.html:<6EE @;766 .error9function9data status headers config; >767 Pwindow.alert9data;<

Page 35: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 35/43

76* @;<76 @<

,erifying %i##ing

The verifyBilling() function shown in 3isting *=.*D is called when theuser clicks on the verify billing button in the shipping view. The billinginformation needs to be updated in the database to ensure that it ispersistent when the customer leaves the website. Also the credit cardinformation can be validated at this point on the server. An $http

POST method is called to the/customers/update/billing route. If the re'uest issuccessful then the view is switched toreview.html. therwise an alert isdisplayed.

Listing 28.27. cart_a"".js-,eri!(#illing *m"lementing the $SS St(les !or the ?ie= @;0L <iles

76B Pscope.verify&illing 8 function9ccv;>76C Phttp.post9:KcustomersKupdateKbilling:76+ > updated&illing- Pscope.customer.billingF6H ccv- ccv@;76D .success9function9data status headers config; >76= Pscope.content 8 :KstaticKreview.html:<76E @;776 .error9function9data status headers config; >

777 Pwindow.alert9data;<77* @;<77 @<

"a+ing the Purchase

The makePurchase() function shown in 3isting *=.*= is called when theuser clicks on the make purchase button in the billing view. This methodsends an $http POST method to the /orders/addroute on the server.The orderBilling orderShipping and orderItems parameters for the 0ST

re'uest. If the re'uest is successful the $scope.customer.cart is initializedto [] since the create order code will have done that on customerdocument in $ongo%&.

 Also if the re'uest is successful then a new order document will have been created in the $ongo%& database. Therefore another $http re'uest

Page 36: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 36/43

is made this time to the /orders/get to get the full list of orders includingthe new one. Then the view is switched to orders.html.

Listing 28.28. cart_a"".js-ma>e%&rchase *m"lementing the $SS St(les !or the ?ie= @;0L <iles

77B Pscope.make0urchase 8 function9;>77C Phttp.post9:KordersKadd:77+ > order&illing- Pscope.customer.billingF6H77D orderShipping- Pscope.customer.shippingF6H77= orderItems- Pscope.customer.cart @;77E .success9function9data status headers config; >7*6 Pscope.customer.cart 8 FH<7*7 Phttp.get9:KordersKget:;

7** .success9function9data status headers config; >7* Pscope.orders 8 data<7*B Pscope.content 8 :KstaticKorders.html:<7*C @;7*+ .error9function9data status headers config; >7*D Pscope.orders 8 FH<7*= @;<7*E @;76 .error9function9data status headers config; >77 Pwindow.alert9data;<7* @;<7 @<

1he fu## Contro##er

The code in 3isting *=.*E shows the full myApp code withthe shoppingController initialization and all of the controller code togetherso you can see how thing fit together. #otice thattheshoppingController definition includes dependencies

on $scope $http and $window. The$window dependency allows us to add the browser alert message on processing errors.

Listing 28.2. cart_a"".js-!&ll *m"lementing the $SS St(les !or the ?ie= @;0L<iles

667 var app 8 angular.module9:myApp: FH;<66* app.controller9:shopping)ontroller: F:Pscope: :Phttp: :Pwindow:

Page 37: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 37/43

66 function9Pscope Phttp Pwindow; >66B Pscope.months 8 F7*BC+D=E76777*H<66C Pscope.years 8 F*67B*67C*67+*67D*67=*67E*6*6H<66+ Pscope.content 8 :KstaticKproducts.html:<

66D Phttp.get9:KproductsKget:;66= .success9function9data status headers config; >66E Pscope.products 8 data<676 Pscope.product 8 dataF6H<677 @;67* .error9function9data status headers config; >67 Pscope.products 8 FH<67B @;<67C Phttp.get9:KcustomersKget:;67+ .success9function9data status headers config; >67D Pscope.customer 8 data<67= @;67E .error9function9data status headers config; >6*6 Pscope.customer 8 FH<6*7 @;<6** Phttp.get9:KordersKget:;6* .success9function9data status headers config; >6*B Pscope.orders 8 data<6*C @;

6*+ .error9function9data status headers config; >6*D Pscope.orders 8 FH<6*= @;<6*E Pscope.set)ontent 8 function9filename;>66 Pscope.content 8 :KstaticK:L filename<67 @<6* Pscope.set0roduct 8 function9productId;>6 Pscope.product 8 this.product<6B Pscope.content 8 :KstaticKproduct.html:<

6C @<6+ Pscope.cartTotal 8 function9;>6D var total 8 6<6= for9var i86< iRPscope.customer.cart.length< iLL;>6E var item 8 Pscope.customer.cartFiH<6B6 total L8 item.'uantity Y item.productF6H.price<6B7 @

Page 38: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 38/43

6B* Pscope.shipping 8 totalY.6C<6B return totalLPscope.shipping<6BB @<6BC Pscope.addTo)art 8 function9productId;>

6B+ var found 8 false<6BD for9var i86< iRPscope.customer.cart.length< iLL;>6B= var item 8 Pscope.customer.cartFiH<6BE if 9item.productF6H.?id 88 productId;>6C6 item.'uantity L8 7<6C7 found 8 true<6C* @6C @6CB if 9Nfound;>6CC Pscope.customer.cart.push9>'uantity- 76C+ product- Fthis.productH@;<6CD @6C= Phttp.post9:KcustomersKupdateKcart:6CE > updated)art- Pscope.customer.cart @;6+6 .success9function9data status headers config; >6+7 Pscope.content 8 :KstaticKcart.html:<6+* @;6+ .error9function9data status headers config; >6+B Pwindow.alert9data;<

6+C @;<6++ @<6+D Pscope.delete5rom)art 8 function9productId;>6+= for9var i86< iRPscope.customer.cart.length< iLL;>6+E var item 8 Pscope.customer.cartFiH<6D6 if 9item.productF6H.?id 88 productId;>6D7 Pscope.customer.cart.splice9i7;<6D* break<6D @

6DB @6DC Phttp.post9:KcustomersKupdateKcart:6D+ > updated)art- Pscope.customer.cart @;6DD .success9function9data status headers config; >6D= Pscope.content 8 :KstaticKcart.html:<6DE @;6=6 .error9function9data status headers config; >

Page 39: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 39/43

6=7 Pwindow.alert9data;<6=* @;<6= @<6=B Pscope.checkout 8 function9;>

6=C Phttp.post9:KcustomersKupdateKcart:6=+ > updated)art- Pscope.customer.cart @;6=D .success9function9data status headers config; >6== Pscope.content 8 :KstaticKshipping.html:<6=E @;6E6 .error9function9data status headers config; >6E7 Pwindow.alert9data;<6E* @;<6E @<6EB Pscope.setShipping 8 function9;>6EC Phttp.post9:KcustomersKupdateKshipping:6E+ > updatedShipping -Pscope.customer.shippingF6H @;6ED .success9function9data status headers config; >6E= Pscope.content 8 :KstaticKbilling.html:<6EE @;766 .error9function9data status headers config; >767 Pwindow.alert9data;<76* @;<76 @<

76B Pscope.verify&illing 8 function9ccv;>76C Phttp.post9:KcustomersKupdateKbilling:76+ > updated&illing- Pscope.customer.billingF6H ccv- ccv@;76D .success9function9data status headers config; >76= Pscope.content 8 :KstaticKreview.html:<76E @;776 .error9function9data status headers config; >777 Pwindow.alert9data;<77* @;<

77 @<77B Pscope.make0urchase 8 function9;>77C Phttp.post9:KordersKadd:77+ > order&illing- Pscope.customer.billingF6H77D orderShipping- Pscope.customer.shippingF6H77= orderItems- Pscope.customer.cart @;77E .success9function9data status headers config; >

Page 40: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 40/43

7*6 Pscope.customer.cart 8 FH<7*7 Phttp.get9:KordersKget:;7** .success9function9data status headers config; >7* Pscope.orders 8 data<

7*B Pscope.content 8 :KstaticKorders.html:<7*C @;7*+ .error9function9data status headers config; >7*D Pscope.orders 8 FH<7*= @;<7*E @;76 .error9function9data status headers config; >77 Pwindow.alert9data;<7* @;<7 @<7B @H;<

(nitia#i-ing the $pp#ication

 /ith the application done you need to create theinitial Customer Order and Product documents in the database. There areseveral different methods of doing this such as using a database scriptcreating an admin interface for you application etc. To make it simplethis example includes a basic #ode.!s script to generate the data that

 youOve seen so far.

The code in 3isting *=.6 shows a basic #ode.!s script that first removesthe customers orders and products collections to clean up if youOvealready been playing around. It then creates a Customerdocument andan Order document and then adds several Product documents.The Productdocuments are added to the Customer documentOs cart andthe Order documentOs items.

Listing 28.3. cart_init.jsl *nitialiing the Sho""ing $art A""lication ata in

0ongo#

67 var mongoose 8 re'uire9:mongoose:;<6* var db 8 mongoose.connect9:mongodb-KKlocalhostKcart:;<6 re'uire9:.KmodelsKcart?model.!s:;<6B var Address 8 mongoose.model9:Address:;<6C var &illing 8 mongoose.model9:&illing:;<

Page 41: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 41/43

6+ var 0roduct 8 mongoose.model9:0roduct:;<6D var 0roductuantity 8 mongoose.model9:0roductuantity:;<6= var rder 8 mongoose.model9:rder:;<6E var )ustomer 8 mongoose.model9:)ustomer:;<

76 function add0roduct9customer order name imagefile77 price description instock;>7* var product 8 new 0roduct9>name-name imagefile-imagefile7 price-price description-description7B instock-instock@;<7C product.save9function9err results;>7+ order.items.push9new 0roductuantity9>'uantity- 77D product- FproductH@;;<7= order.save9;<7E customer.save9;<*6 console.log90roduct L name L Saved.;<*7 @;<** @* 0roduct.remove9;.exec9function9;>*B rder.remove9;.exec9function9;>*C )ustomer.remove9;.exec9function9;>*+ var shipping 8 new Address9>*D name- :)ustomer A:*= address- :Somewhere:

*E city- :$y Town:6 state- :)A:7 zip- :CCCCC:* @;< var billing 8 new &illing9>B cardtype- :Gisa:C name- :)ustomer A:+ number- :7*BC+D=E6:D expiremonth- 7

= expireyear- *6*6E address- shippingB6 @;<B7 var customer 8 new )ustomer9>B* userid- :customerA:B shipping- shippingBB billing- billing

Page 42: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 42/43

BC cart- FHB+ @;<BD customer.save9function9err result;>B= var order 8 new rder9>

BE userid- customer.useridC6 items- FHC7 shipping- customer.shippingC* billing- customer.billingC @;<CB order.save9function9err result;>CC add0roduct9customer order :%elicate Arch 0rint:C+ :arch.!pg: 7*.BCD :Giew of the breathtaking %elicate Arch in 2tah:C= $ath.floor99$ath.random9;Y76;L7;;<CE add0roduct9customer order :Golcano 0rint:+6 :volcano.!pg: BC.BC+7 :Giew of a tropical lake backset by a volcano:+* $ath.floor99$ath.random9;Y76;L7;;<+ add0roduct9customer order :Tikal Structure 0rint:+B :pyramid.!pg: =.C*+C :3ook at the amazing architecture of early America.:++ $ath.floor99$ath.random9;Y76;L7;;<+D add0roduct9customer order :Wlacial 3ake 0rint:

+= :lake.!pg: DD.BC+E :Givid color crystal clear water from glacial runoff.:D6 $ath.floor99$ath.random9;Y76;L7;;<D7 @;<D* @;<D @;<DB @;<DC @;<<

Suary

In this chapter you got to go through the process of implementing a basicshopping cart using the #ode.!s $ongo%& and AngularJS webapplication stack. ,ou were able to define a solid model in $ongoose tosupport customers products orders and the full checkout process.

Page 43: Node Shopping Cart

8/9/2019 Node Shopping Cart

http://slidepdf.com/reader/full/node-shopping-cart 43/43

 Also in this chapter you should have recognized the benefits of being ableto easily switch between "T$3 template views in AngularJS and yethave all of your data bound to that page automatically. The data binding

 value also became very apparent when we were able to update the

$ongo%& database with only a simple function calls becausethe $scope data was consistently kept up to data as we added items to thecart and change shipping and billing information.

e3t

In the next chapter you get a bit of different look as you look at some richinternet application concepts.