This tutorial is part of the « E-commerce website with Strapi, Nuxt.js, GraphQL and Strip »
- 👋 Intro & Setup
- 🏗️ Homepage (part 1)
- 🍔 Restaurant page (part 3) - current
- 🛒 Shopping Cart (part 4)
- 🔐 Authentication (part 5)
- 💵 Checkout (part 6)
- 🚀 Bonus: Deploy (part 7)
Note: The source code is available on Github.
Congratulations, you successfully displayed the list of restaurants! This was the first major step. The next step is to create dishes that go with the restaurants.
Step 1 - Create a new Dishes collection type
Every restaurant sells dishes, which also must be stored in the database. So, you now need to create a new Content Type named dish
.
- Go to Plugins Content-Type Builder in the main navigation.
- Click on Create new collection type.
- Type
Dish
for the Display name, and click Continue. - Click the Text field.
- Type
name
in the Name field. - Switch to the Advanced Settings tab, and check the Required field and the Unique field settings.
- Click on Add another field.
- Choose the Media field.
- Type
image
under the Name field, and check the Single media option then click Finish. - Click on Add another field.
- Choose the Number field, Number format: decimal (ex: 2.22).
- Type
price
under the Name field, then click Finish. - Click on Add another field.
Choose the Relation field, this one is a bit more specific. Your purpose here is to tell to Strapi that every dish can be related to a restaurant. To do so, create a one-to-many relation, restaurant has many Dishes as below, then click Finish.
Finally, click Save and wait for Strapi to restart.
Well done! You created your second Content Type. The next step is to add some dishes to your database.
Step 2 - Create new entries for the "Dish" collection type
Add some entries.
- Go to Content Manager
- Click on Collection types > Dish in the navigation.
- Click on Add new entry.
- In the Name field, type the name of your favorite dish.
- In the Media field, import a new cover. If you're lacking some inspiration, you can check Deliveroo 🙈 .
- In the Price field, type a decimal number.
- In the Restaurant field at the right sidebar, select a restaurant.
- Click Save, and Publish.
Create as many dishes as you would like to see in your app. If you're lacking some inspiration, you can check Deliveroo 🙈 . In the next step, you will be able to request them from the Strapi API.
Step 3 - Set Roles & Permissions
We have just added some new dishes. We need to make sure that the content is publicly accessible through the API:
- Click on General > Settings at the bottom of the main navigation.
- Under Users & Permissions plugin, choose Roles.
- Click the Public role.
- Scroll down under Permissions.
- In the Permissions tab, find Dish and click on it.
- Click the checkboxes next to find and find**O**ne.
- Finally, click Save.
It looks you are going to the right direction. In the next step, you will display these dishes in your Nuxt.js app.
Step 4 - Creating a new Dishes page
At the end of this section, you should have a Dishes page that looks like this:
Inside the pages
directory, create a new directory restaurant
. Nuxt reads all the .vue
files inside the pages
directory and automatically creates the router configuration for you, checkout the Pages directory to learn more about this.
To create restaurants pages we need to add a new .vue
file with the restaurant name, but because we don't know the name of the page due to it coming from the Strapi API, we will need to create a dynamic page, to do so you need to add an underscore before the .vue
file name or before the name of the directory, if you want the directory to be dynamic.
Dynamic pages can be created when you or you don't want to have to create the same page over and over again.
Let’s create a new _id.vue
file inside the restaurant
directory and prefix it with an underscore, like this pages/restaurants/_id.vue
, and copy/paste the following code in it.
1 // pages/restaurants/_id.vue
2 <template>
3 <div class="uk-container uk-container-xsmall">
4 <span class="uk-heading-small">
5 // Link to go back to the previous page
6 <NuxtLink class="uk-button uk-button-text" to="/">
7 <span uk-icon="arrow-left"></span> go back
8 </NuxtLink>
9 </span>
10
11 // Displaying dishes
12 <div v-for="dish in dishes" :key="dish.id">
13 <div class="uk-card uk-card-default uk-child-width-1-2 uk-margin" uk-grid>
14 <div class="uk-card-body uk-card-small">
15 <h2 class="uk-card-title">{{ dish.attributes.name }}</h2>
16 <p>{{ restaurant.data.attributes.name }}</p>
17 <p>{{ dish.attributes.price }} €</p>
18 <button class="uk-button uk-button-primary uk-margin-xlarge-top">
19 Add to cart
20 </button>
21 </div>
22 <figure class="uk-card-media-right uk-cover-container">
23 <img
24 :src="getStrapiMedia(dish.attributes.image.data.attributes.url)"
25 :alt="dish.attributes.image.data.attributes.alternativeText"
26 />
27 </figure>
28 </div>
29 </div>
30 </div>
31 </template>
32
33 <script>
34 import { getStrapiMedia } from '@/utils/media'
35 import restaurantQuery from '@/apollo/queries/restaurant'
36 export default {
37 data() {
38 return {
39 restaurant: Object,
40 }
41 },
42 apollo: {
43 restaurant: {
44 prefetch: true,
45 query: restaurantQuery,
46 variables() {
47 return { id: this.$route.params.id }
48 },
49 },
50 },
51 computed: {
52 dishes() {
53 if (!this.restaurant?.data) return []
54 return this.restaurant.data.attributes.dishes.data
55 },
56 },
57 methods: {
58 getStrapiMedia,
59 },
60 }
61 </script>
The restaurant page display a “go back” link to go back to the previous page, using apollo wi request and display the current restaurant dishes.
Again, let’s create the graphql
template. Add a new file apollo/queries/restaurant.gql
:
1 query Restaurant($id: ID!) {
2 restaurant(id: $id) {
3 data {
4 id
5 attributes {
6 name
7 dishes {
8 data {
9 id
10 attributes {
11 name
12 price
13 image {
14 data {
15 attributes {
16 url
17 }
18 }
19 }
20 }
21 }
22 }
23 }
24 }
25 }
26 }
Our restaurant.gql
query, ask for specific fields on the restaurant object, and the dishes
field returns an array of dishes.
Conclusion
The dishes page should be accessible from [http://localhost:3000/restaurants/1](http://localhost:3000/restaurants/1)
where 1
is the id of the restaurant.
Nothing particular here: exactly like for the restaurants, you defined a template and then added the logic in the script section.
🛒 In the next section, you will learn how to create a full featured shopping card.
Pierre created Strapi with Aurélien and Jim back in 2015. He's a strong believer in open-source, remote and people-first organizations. You can also find him regularly windsurfing or mountain-biking!