This tutorial is part of the « E-commerce website with Strapi, Nuxt.js, GraphQL and Strip »
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.
Every restaurant sells dishes, which also must be stored in the database. So, you now need to create a new Content Type named dish
.
Dish
for the Display name, and click Continue.name
in the Name field.image
under the Name field, and check the Single media option then click Finish.price
under the Name field, then click Finish.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.
Add some entries.
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.
We have just added some new dishes. We need to make sure that the content is publicly accessible through the API:
It looks you are going to the right direction. In the next step, you will display these dishes in your Nuxt.js app.
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.
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!