If you find any errors, typos or have general feedback, select the text and click CTRL+ALT+ENTER.

Introduction

In this tutorial, you’ll learn how to extend your AngularJS Pizza app by adding a shopping cart and custom pizzas interface. Please complete first part of this tutorial via the link before going ahead.

We are going to extend the previously created application by adding Cart and My Pizza pages. The Cart contains a list of names and prices, and the Delete from Cart button, as well as fields for entering phone number and address. The main menu is complemented with Add to Cart buttons. My Pizza page is designed similarly to the main menu, and we will also add Add to Cart and Remove from the list of custom pizzas buttons.

In the Cart page, will be an Order button to send a list from cart to the Orders database collection, then shopping cart is cleared. There will also be a button to empty the shopping cart.

The pizza PizzaCreator will now ask for the name and description of your custom pizza. There will also be a button to clear the list of selected ingredients.

In navbar, a field for a quick search by pizza name will be added. The search will be available on pages Menu, My pizza and Cart , as they have a similar structure. 

Before you begin

Tutorial level: advanced.

This tutorial assumes you have already created The Pizza app.

Try it yourself

Attachments

Creating from the backup

You can extend this app app by following step-by-step tutorial below or create it from the backup.

To create an app from the backup:

  1. Click Create new app.
  2. Type an app name.
  3. Click From backup and select the project backup file.
  4. Click Create.

You still have to extend the database manually as described in this section below. If you’ve already created the database, find the X-Appery-Database-Id:
database_id_2

And paste it to PizzaDelivery_settings > database_id:database_id1

Adding new pages

Let’s continue developing your app. The app already has index, Menu, Details and PizzaCreator pages. We’re going to create two more pages.

  • Inside the app builder, go to CREATE NEW > Page. Add Custom and Cart pages:
    001-App_Pages
  • Go to Project > Routing and set the following routing:
    002-Page_Routing
  • Go to the index page and add two more Link components to Navs
  • For the third Link set properties Text = My pizza and ng-click with the following code:

    003-Link3_properties
  • For the fourth Link set properties Text = Cart and ng-click with the following code:

    004-Link4_properties

Now you can run Test to check navigation.

Extending database

To continue creating the app database, click DATABASE in the builder or go to https://appery.io/database.

Open the PizzaDelivery database. There are already created Menu, Ingredientsand CustomPizza collections. 

Instead of creating collections manually, you can download .zip archive and unzip it. There are exported Cart and Orders collections as .json files. Just click Import a collection, type its name and click Choose file to select the previously unzipped files.

Cart collection

  • Create a Cart collection.
  • Add a column pizzaId of String type for referring to existing pizza from Menu or CustomPizza collection.
  • We are going to implement pizza search in other collections by pizzaId. To make it faster, add a column named custom of Boolean type. It will show whether pizza is custom (if True):
    005-Cart_collection

Orders collection

  • Create an Orders collection.
  • Add phone and address columns of String type.
  • Add a column items of Array type. This is an array of pizzas containing a flag custom that shows whether pizza is custom (if True):
    006-Orders_collection

Importing database services

We’ve already imported some services from the PizzaDelivery database. 

Inside the app builder, go to CREATE NEW > Database Services. Check the following services:

  • Cart collection: create, delete, list
  • Orders collection: create
  • CustomPizza collection: delete, list, read

The added services appear under Services section:
007-Imported_services

Building Scope of index and Menu pages

We are going to prepare SCOPE of the index page for work with custom pizzas.

  • Go to SCOPE of the index page.
  • Open the method init() that will be automatically run when the app starts. Paste the following code in the very beginning of that function:
  • Before triggering the list services, variables that will keep their responses should be created. Create two variables customPizzas and list with type of Array:
    variables_created
  • Now, let’s invoke the menu_list and custom_pizza_list services with the help of snippets, and bind their responses to the variables via mapping. In the editor, click the arrow to filter snippets, select Invoke service, and click Insert snippet.
  • Then, delete the text “service_name” in the code and  click CTRL+SPACE to get the drop-down with all the available services and autocomplete the needed service: PizzaDelivery_CustomPizza_list_service:
  • Sample code will be added to the function. The first (upper) Mapping button is for Before send mapping, the second one is for Success mapping.
  • Click the lower Mapping and create the following by dragging the $ sign over the customPizzas variable to the right:
    custompizzas
  • Click Save & Replace. This will store the response of customPizzas list service to the customPizzas variable.
  • Place the cursor below the code and invoke the PizzaDelivery_Menu_list_service the same way, then map its response to list variable. Your init() function should look like the following:

    For now, to change the mapping, you should remove the generated code and create the mapping from scratch by clicking Mapping again. Visual mapping editing will be implemented soon.

  • Now, customPizzas and list arrays are available from scope of any screen (this is how index screen works).
  • Go to the Menu page SCOPE and clear the method init().

Building a Custom page

The Custom page is designed to handle custom pizzas.

  • Go to the Custom page and add a Grid Layout similar to the Menu page.
  • Set 5 cells (select the GridRow and click + three times).
  • For the first cell, set the Columns properties: Xtra-Small = 6, Large = 4:
    008-GridCell1_properties
  • For the second cell, set the Columns property Xtra-Small = 2:
    009-GridCell2_properties
  • For the third and fourth cells, set the Columns properties Xtra-Small = 2 and Large = 1:
    010-GridCell3_properties011-GridCell4_properties
  • For the fifth cell, set the Columns property Xtra-Small = 4 and Hidden = True for Medium, Small, Xtra-Small:
    012-GridCell5_properties
  • Select the GridRow and add property ng-repeat = item in customPizzas:
  • 013-GridRow1_properties_
  • Drag a ListGroup to the first cell, set its property Linked = True so a pizza name looks clickable:
    014-ListGroup1_properties
  • Select thw ListGroupItem, set property Text = {{item.name}} and add property ng-click= goToDetails(item._id) (similarly to Menu):
    015-ListGroupItem1_properties
  • Drag a Text component to the second cell, set its property Text = {{item.price | currency }}:
    016-Text_properties
  • Add a Button component to the third cell, set its Type = Success, clear the Text property. Set the white shopping cart icon:
    017-Button_properties
  • Add a Button component to the fourth cell, set its Type = Danger, empty Text property. Add property ng-click = removePizza(item). Set a white trash bin icon:
    018-Button_properties
  • Add a Text component to the last cell, add property ng-bind = item.consist (similarly to Menu):
    019-Text_properties
  • Go to the page SCOPE and add a function removePizza(item) with the following code: 
    The code above triggers the CustomPizza delete service, but without the mapping and code snippets as described here. You can choose which option you like more.
  • Now you can run Test to make sure Custom page is filled with custom pizzas from the database. If you still haven’t created any pizzas, add them in PizzaCreator and refresh the page.

Building a PizzaCreator page

The PizzaCreator page allows users to create a custom pizza recipe and submit it to an administrator review. We need to change it so a new pizza is also added to customPizzas array:
020-Constructor_page

  • Go to the PizzaCreator page
  • Drag a Form component to the page and place it above the Save button.
  • Drag an Input and a Textarea components to Form groups.
  • Set the Input properties Placeholder = Pizza's name, ng-model = customPizza.name:
  • Set the Textarea property placeholder = Descriptionng-modelcustomPizza.about:
    022-Textarea_properties
  • Drag a Text component above the Input and set TextHow would you like to call your pizza?:
    023-Text_properties
  • Drag a Text component above the Textarea and set Text = Describe your pizza:
    024-Text_properties
  • Select the Save button and add property ng-disabled = !customPizza.name so that it is disabled until you enter a pizza name:
    025-Save_Button_properties
  • Drag a Button component and place it after the Save button, and set its properties Text = Clear list and ng-click = clearList():
    026-ClearList_Button_properties
  • Go to SCOPE, open the method init() and add the following code in the beginning of it:

  • Replace the code of savePizza() with the following code (here, we delete the Modal code, add custom pizza to both database and customPizzas array, and clear the list and name after saving pizza):
  • Add a function clearList() with the following code:
  • Now, you can run Test to make sure the added pizza appears on MyPizza page. If you click a custom pizza name, its description won’t be displayed as the Details page looks for pizzas only in the Menu list. We need to pass the second argument custom via Routing what means the pizza is in the custom list.
  • On the Custom page, select the item with pizza name and add the second function parameter to ng-click = goToDetails(item._id, true):
    027-ListGroupItem1_properties
  • Go to the SCOPE of the Menu page. Add the second argument custom to the method goToDetails(),and replace its code with the following:
  • Go to Routing and, for Detailsset the following path: /Details.html/:id/:custom 
  • Go to the SCOPE of the Details page and replace the code of method init() with the following code:
  • Now, you can run a test to make sure a description is opened on custom pizza name click.

Adding shopping cart

Adding addToCart buttons

  • Go to the Menu page and select GridRow.
  • Add one more cell and drag Text from the third cell to the new one.
  • For the new cell, set properties similar to the third cell (Xtra-Small = 2, Large = 4 and Hidden = True for Medium, Small, Xtra-Small):
    028-GridCell4_properties
  • For the third cell, remove all properties Hidden = True and remove Large = 4:
    029-GridCell3_properties
  • Drag a Button to it and set its Type = Success, empty the Text and set a shopping cart icon (similarly to Custom page), set property ng-click = addToCart(item):
    030-Button_properties
  • Go to the Custom page, select a green shopping cart button, set property ng-click = addToCart(item, true). The last parameter means the pizza is custom:
    031-Button_properties - Copy17
  • Go to SCOPE of the index page. Add a function addToCart(item, custom) so that this method is available from any page. The method will take an item which is a pizza object, and read its id. Flag custom shows whether the pizza is custom, and its value will be saved to database Cart collection. Cart array will store a list of all the pizzas in the cart which we’ll add later. Paste the following code:

Building design of Cart page

  • Go to the Cart page. Drag a Grid Layout to the page and add 3 cells.
  • For the first cell, set properties Xtra-Small = 8, Large = 4:
    032-GridCell1_properties
  • For other cells, set Xtra-Small = 2:
    033-GridCell2_properties034-GridCell3_properties
  • For GridRow, set ng-repeat = item in cart:
    035-GridRow1_properties_
  • Drag a ListGroup to the first cell, set ListGroupItem property Text = {{item.name}}:
    036-ListGroupItem1_properties
  • Drag a Text component to the second cell and set its property Text = {{item.price | currency}}:
    037-Text_properties
  • Drag a Button component to the third cell, set Type = Danger, remove Text, set white recycle bin icon and set ng-click = removeFromCart(item):
    038-Button_properties
  • Add a Text component under the Grid, set its Text = Total: {{totalPrice | currency}}:
    039-Text_properties
  • Add a Form component and fill it out similarly to the PizzaCreator. Drag a Text component, then Input, then one more Text and Textarea:
    040-Form
  • Set the Input property ng-model = phoneNumber, placeholder = Phone number:
    041-Input_properties
  • Set Textarea property ng-model = addressplaceholder = Address:
    042-Textarea_properties
  • Add a Button in the end of the Form (or under it). Set its Text = Order, ng-click = sendOrder(). Add attribute ng-disabled= !phoneNumber || !address so that the Button is disabled if some field is not filled:
    043-OrderButton_properties
  • Add one more Button component and set its TextClear cart, ng-click clearCart():
    044-ClearCartButton_properties

Building Scope of Cart page

  • Go to SCOPE of the Cart page. The code of method init() adds cart array to the index SCOPE. An item with attributes pizzaId and custom will be saved to database. Pizza name and price will be also copied to the cart array:
  • Add method removeFromCart(item):
  • Add method clearCart() to remove items from cart:
  • Add method sendOrder() that generates items array, phone number and address, and saves them in Orders collection. It clears the cart after the success message is displayed:
  • Now you can run a test to check how your shopping cart works.

Adding filter for a quick search

  • Go to DESIGN of the index page
  • Select Navbar and add a Form component to the right (bottom on Xtra-Small screen) container. Remove the second FormGroup.
  • Drag an Input component to the remaining FormGroup, set its properties placeholder  = Quick search... and ng-model = search.name:
    045-Input_properties
  • Go to SCOPE of the index page and add the following code in the beginning of the method init():
    This is an object for filtering pizzas by name.
  • Go to DESIGN of the Menu page.
  • Select the GridRow and set the property ng-repeat= item in list | filter: search:
    046-GridRow1_properties
  • Go to DESIGN of the Custom page and set GridRow property ng-repeat= item in customPizzas |filter: search:
    047-GridRow1_properties
  • Go to DESIGN of the Cart page and set GridRow property ng-repeat= item in cart | filter: search:
    048-GridRow1_properties
  • Now you can run a test to check how filtering works.

Testing the app

It’s time to test the app. Click TEST button and the Menu opens:
049-Test_Menu

Let’s try to filter pizzas by name:
050-Test_Menu_filter_

Navigate to the PizzaCreator to create your own pizza:
051-Test_Constructor

After your recipe is ready, click the Save button:
052-Test_Constructor_Added

Let’s check the list of custom pizzas:
053-Test_Custom

Now open your shopping cart:
054-Test_Cart

Click the Order button to order your pizzas:
055-Test_Cart_Ordered