Creating a Shopping Cart with the Data Store Component

The Data Store component allows you to store and edit local data in a simple local storage driven database. You can use this component to create a shopping cart, favorite products list, task lists etc. In this tutorial we will show you how to add a shopping cart functionality to your site.

Local Storage vs Session Storage

You can select between storing your data in the browser local storage or session storage. What are differences?

Local Storage

The Local Storage stores data with no expiration date, and gets cleared only through JavaScript (Wappler dynamic events) or clearing the Browser cache / Locally Stored Data.

Session Storage

The Session Storage stores data only for a session, so the data is stored until the browser or the tab is closed.

Products page overview

We created a server action, which returns records from our database table. On the products page we created repeating row, which lists products from a database. The dynamic data used here is product id, name, price, description and an image per each of the products.
There is also an Add To Cart button for each of the products, it will be used to add the selected product into the shopping cart later.
You can add more info in the repeat region, this is just an example:

Creating the Shopping Cart

Let’s setup our shopping cart. The functionality we are going to add in the steps below include: adding a product into the shopping cart, updating a product quantity, removing a product from the shopping cart.

Define Data Store Schema

The first thing we need to do is to define the Data Store Schema. In order to do this, we need to add the Data Store component on the page. Select App and click Add New Component:

Select Data and add Data Store:

Let’s change the Data Store ID to something more meaningful, like cart:

In order to keep the products in the shopping cart, even if the users leave the site and come back later, we will use the browser local storage. So - don’t check the Use Session Storage checkbox.
Then click the Define Data Store Schema button:

Select cart and click the Add New Item button:

Then select Add Variable. We need separate variables for the different dynamic data items you need to use in the cart. In the most basic cases you would need: product id, product name, price and quantity.

We call this variable prd_id as it will store the product ID. Set the data type, which is going to be stored here, in our case this is a number:

Do the same with the rest of the variables which you need for your shopping cart:

We are done setting up the Data Store Schema.

Add products to the shopping cart

We already have the shopping cart structure defined, so let’s start with adding product data into it. Select the Add To Cart button and add a new Dynamic Event:

Select Mouse > Click:

And select what needs to happen on click:

We need a functionality that automatically updates the product quantity, if the product has already been added to the cart, or insert it as a new product there if it’s not in the cart yet. So select Update or Insert Record(s) action and click the add button:

In order to check if the product is already in the cart, we need to use it’s unique id. So we are going to check the dynamic product ID, returned by our database. Under Which Records click the dynamic data picker to select your unique product ID:

This is the product ID binding, located under the repeat region in the data picker:

Then scroll down to New Values and select the dynamic values which you want to insert in your shopping cart:

Just select the corresponding dynamic bindings, under your repeat region in the data picker:

As we explained a few steps above, we need the quantity to automatically update if the product has already been added to the shopping cart:

This quantity field here is the quantity variable you added to the Data Store Schema earlier. For its value enter:

`quantity + 1` 

Where the word quantity is the name of the quantity variable in the Data Store Schema.
Note that the value is enclosed in backticks:

Click select when you are done:

Setup the shopping cart layout

In our example we will show you how to display your shopping cart content in a table, inside a modal. Every time you add an item to the cart, the modal will fade in and show its content. Add new component:

Open Components and select Dynamic Modal:

Let’s change the default modal title to Shopping Cart:

Then we want to have two buttons at the modal footer - Continue Shopping (which closes the modal) and Checkout (which redirects you to a checkout page):

Click the default Save Changes button and remove it:

Then rename the default Close button to Continue Shopping:

And add another element after it:

Under Forms select Anchor Button:

Change the Anchor Button text to Checkout:

We set its style to Primary:

And then select the link it should point to:

This is our checkout page. You can select this later, if you haven’t added a dummy chekout page yet:

Then we remove the default content in the modal body:

We want to add a dynamic table, listing the Data Store component content. Select modal body and add new component inside:

Under Generators select Bootstrap 4 Table Generator:

And select the dynamic data source for it:

Select the data element under the Data Store component:

Table columns have been automatically added, depending on your Data Store schema. We need another column, where we will place 3 buttons - increase quantity, decrease quantity and remove item. So we add another column in to the table:

Let’s call it Actions and set its content type to custom:

Then customize the table layout and options. In our case we don’t need to show the item id and product unique id to the users, so we delete these columns:

Click OK when you are done customizing the table options and layout:

You can select the modal and change its size, if needed:

As we are using the Data Store component for dynamic data source, there is no data displayed on the page - its initial values are empty, so you won’t see anything repeated in the table. In order to be able to add custom data in the dynamic table we need to turn the App Connect mode off:

Then click in the custom column which we created and add a new component:

Select Button:

We will need 3 buttons here - decrease quantity, increase quantity and remove item. So just duplicate the buttons 2 times.

Select the first button, this will be the decrease quantity button. Double click to edit, delete its text and click the font awesome button:

Find a suitable icon - for example the following one:

Do the same for the other two buttons - increase quantity and delete item. When you add the icons in the buttons let’s style them. For the increase and decrease quantity we set the style to Primary and size to Small:

For the delete item button we set the style to Danger and size to Small:

We are done with our simple shopping cart layout.

Update shopping cart items quantity

Now let’s make buttons work - we are going to add the increase/decrease quantity and remove item functionality to them. Select the decrease quantity button and add new dynamic event:

Select Mouse > Click:

Then select what needs to happen on click:

Under the Data Store component, select Update Record(s):

Then, let’s select which record to update. Here we are going to use the default record ID returned by the Data Store component:

Its value should be the $id element under the table repeat region, in the data picker:

Here we need to update (decrease) the quantity so click the dynamic data picker icon for the quantity field:

We need to subtract 1 from the current quantity, so we select the quantity binding under the table repeat and add - 1 to it, so it becomes: quantity - 1:

Click Select:

We only need the decrease quantity button to be available if the quantity is more than 1. With the button still selected, add new dynamic attribute:

Select Input > Disabled:

And then click the dynamic data picker, to select when should it be disabled:

Select the quantity binding, under the table repeat region and add == 1 to it:

Now, select the increase quantity button and add a new dynamic event:

Select Mouse > Click:

And select what needs to happen on click:

Under the Data Store component select Update Record(s):

Then select which record to update. Here, again, we are going to use the default record ID returned by the Data Store component:

Its value should be the $id element under the table repeat region, in the data picker:

Here we need to update (increase) the quantity, so click the dynamic data picker icon for the quantity field:

We need to add 1 to the current quantity, so we select the quantity binding under the table repeat and add + 1 to it, so it becomes: quantity + 1:

Click Select:

Remove items from the shopping cart

The only thing left is to add the remove item functionality to the delete button. Select the button and add new dynamic event:

Select Mouse > Click:

Then select what needs to happen on click

Under the Data Store component select Delete Record(s):

Again we use the record ID returned by the Data Store component:

And select the $id under the table repeat region:

And you are done, your buttons are now fully functional and you can update the items quantity or remove items from the cart.

Show the cart when an item is added

We want to show the cart, when an item has been added to it. This means we need to show the modal once the Add To Cart button is clicked.
We can turn on the App Connect mode now, then select the Add To Cart button:

We already have a dynamic event added on click (add product to cart), so let’s add another one:

Under Modal select Show and add it to the events list:

Click Select:

Display total price in the cart

You can use the App Connect Data Formatter to display the total price of all the items in the cart. You can do this per row (per item) and for the whole cart.
In our example we will show you how to do this for the whole cart, as we didn’t add a total column per row.

We’d like to show the totals below the table, so select the table and click - insert after:

Select Content > Paragraph:

Let’s align the paragraph right:

Then double click to edit its default text. We enter: Total Amount:

And then we click the dynamic data picker icon:

Select the data element under the Data Store component:

We need to sum each row (or item) totals. So each product price multiplied by its quantity. So the result will be: product1 * quantity1 + product2 * quantity2 ... product99*quantity99

Open Collections and select Sum:

Click Property and click the dynamic data picker icon:

Select the product price and add * quantity to it:

Now we have the sum of each row (or item) total price:

Click Select:

And you are done. Just format the text as you need:

Show shopping cart button

A useful addition to our shopping cart would be a button which opens it, so you can preview its contents. This button will also show how many items are currently added in the cart.
Let’s start by adding a button somewhere on the page:

We add a regular button:

Select a style for it:

Then double click its text and enter Shopping Cart:

We want to show the number of items added in the cart, so click the dynamic data picker button:

Select the data element under the Data Store component, then click the data formatter icon:

Open collections and select sum:

Select a property to sum:

This should be the quantity for each of the rows/items:

Click Select:

And you are done. Now add new dynamic event:

Select Mouse > Click:

And select what needs to happen on click:

Under Modal select Show and add it:

Click Select:

Now you have a button which shows the number of items added in the shopping cart and also opens it on click.

Checkout Page Overview

In order to be able to use the Data Store data on another page, let’s say a checkout page there are two requirements you need to follow:

  1. The App ID must be the same as on the page where you defined the Data Store:

  1. The Data Store component ID must be the same as the one used for the shopping cart:

Following these two simple rules you can create your own custom checkout page:

Here you can use the data from the Data Store component to add a dynamic table, the same way as in your shopping cart:

The data from the Data Store component is available in the data picker dialog:

So - go ahead and finish the Checkout Page layout, using what you learned in this tutorial :slight_smile:

Conclusion

That’s how easy you can add a shopping cart functionality using the Data Store component. This is just a simple example of what can be done, you are free to fully customize every aspect of this shopping cart tutorial as per your needs.

8 Likes

Very cool addition. and nice tutorial @teodor

2 Likes

Very clear tutorial - it demonstrates how easy it is to use the new Data Store component. It will be a really useful feature.

How can I check if an item has already been added? In a repeat I may want to indicate that an item has already been added to the cart or wish list etc. - by applying a style or disabling a button etc. Something like cart.data.contains(id) ?

How would one do products with options and price diffference?

My use case is theatre tickets. So it would be one ‘product’ with options being the different dates the show runs. Also two of the nights are cheaper nights?

Would I have to create 14 different products for a 14 night show?

Brad, you could have 3 variables - movie, screening, qty.

The movie could be the ID in your database, the screening would be a dropdown of the days and times of the movie and the qty is just a number.

I’d be disinclined to store prices within data store incase some smart ass comes along and decides to change the ticket price in their browser. I’d always check the price against a value in the database before checking out.

3 Likes

Whoa, how easy is that. The following is the original

Adjusting (editing) the value

Turns it into

That’s why it’s not what you send to your payment provider Ben :slight_smile:
You use these values to show the content to the users and on the serverside just filter your database table with products by the product IDs, then use the values returned from there with the Stripe (or any other) API in Server Connect.
You don’t send clientside values :slight_smile:

1 Like

This is why you must always check/validate server side. Go check out Burp (Burp Suite) and scare yourself Ben. Grab yourself a free community edition and then audit your sites and see how easy it is to inject pretty much whatever you like in to whatever you like, if no attention has been paid to securing such variables server side (incredibly common) then you’ll probably find yourself going back to the drawing board…

Max’s comment is very good advice.

Nice introduction with a very friendly pen-tester STÖK

3 Likes

Don’t store pricing locally. Just id and quantity. Not even if you later checkout using server data.

It is not just to avoid tampering with the data. It is bad UX.

What if the price of a product changes or the stock of it? The user would come back to the page and see a wrong price or think there is inventory when there isn’t. Then he continues filling the forms (shipping address, payment data, etc) and when you finally check against the database he gets an error that there is no stock or he gets charged another price.

When a user returns to your page and retrieves cart content always perform a check against server for latest price and stock. You might want to lock prices and stock for that user or do yet another check just before the final step. That is up to you. Just don’t store pricing locally.

This tutorial is just an example on how to use a component on a real functionality but every wappler needs to make sure they do their homework. Specially when it comes to security.

5 Likes

That’s right, when it comes to changing prices and stock it’s a bit more complicated.
The tutorial just shows how to build a very basic cart, where the price/stock isn’t going to change during the checkout process.
You will need to adjust it as per your site needs, once you know the basics of how the data store component works :slight_smile:

2 Likes

To answer my own question, this seems to be a solution:
cart.data.values('id').contains(id)
…but perhaps there are others.

1 Like

Using your solution:

image

1 Like

Wow this seemingly (so I’m told) easy thing to do just got quite complicated.

Well there is nothing too complicated Brad :slight_smile:

There is nothing in the tutorial that shows how to do this. As Ben has shown this is hardly a very secure way to do business on the web. Is there more tutorials to actually make it work coming?

I’m following this thread closely because I really want to believe that this could be a solution. But the more I read the more muddy the waters get. ;-(

I would really love to see a fully working site using this method.

2 Likes

The tutorial shows how to setup your shopping cart functionality on your page/site.
We don’t know which payment processor’s API are you using so the serverside part is left for you to setup, using the API Action.
This is usually explained in your payment processor docs (PayPal, Stripe etc.)

There is nothing scary about this - it’s like submitting form values to your server action …

1 Like

I’m rebuilding my cart so it no longer uses the Local Storage for the item details (mainly the price!) but instead just stores the ID and then gets the info from the database. I’ve put in a Server Connect in the cell that shows the price and it’s working fine.

What’s the best way to get the total of all the items in the cart? I just did a sum of the array in the local storage previously so need to change that. I’ve create a variable to hold the total but I’m not sure how I add to it in the repeater.

Hope that makes sense!