This exercise will demonstrate how to display a product or item’s information from the API data. You should route to an item’s page from the list of items and displays its information. More details are described in the acceptance criteria below.
Table of Contents
Objective
Build a responsive web page that displays the item’s information from API data
Description
This is a continuation of the exercise “Fetch and display menu items“. The goal of this exercise is to build a page that looks similar to the prototype shown below.
Prototype of the item’s page
A page for an individual item should be opened when the respective item is clicked from a list of menu items,
The exercise can be done with HTML, CSS, and JavaScript, but it is recommended to use modern front-end libraries or frameworks such as React.js, Vue.js, or Angular. The solution provided is in Vue.js and also uses Vuetify.js which is a material design UI library for Vue.js.
The menu items are saved in a database and the data is made available through REST API.
API documentation:
Get a single item:
fetch("https://my-json-server.typicode.com/projectecode/demo/menu/1")
.then((res) => res.json())
.then((json) => console.log(json));
Response
//output
{
"id": 1,
"title": "Cheese Burger",
"img": "https://cdn.pixabay.com/photo/2017/12/09/23/04/bread-3008950_960_720.jpg",
"price": "3.75",
"description": "Our burger is seasoned with a pinch of salt, pepper and onion powder. It is topped with pickles, lettuce, tomato, onions, and American cheese. Assembled on a perfectly toasted bun.",
"calories": "450",
"proteins": "32gm",
"category": "Entree"
}
Template:
You can use the following template to fork and get started:
Acceptance criteria
- The item’s title and image on the menu page should include a hyperlink to open the respective page for the item.
- The id of the item should be passed to the new component (page) as a route parameter or through props.
- Fetch the item’s details from the API.
- Display item’s image, title, cost, category, and description as shown in the prototype design
- Add an “Add to order button
- The text on the “Add to order button should be updated to show “View order when clicked.
- Add a “Main menu” button. Clicking this button should navigate back to the Menu page.
- The webpage should be responsive
- Use material design as a standard design practice
Hints
- Use the native
fetch
function in javascript or libraries such asaxios
to get data from an API. - The REST endpoint for GET method is
'https://my-json-server.typicode.com/projectecode/demo/menu/1'
- Use a design library such as bootstrap as a boilerplate for making responsive design
- Add a flag to check if the item is added to the order. If the item is added to the order, set it to true and update the text on the button
Solution Walkthrough
Menu component Menu.vue
is updated to add a router link that will open the item component Item.vue
.
<!-- Menu.vue -->
<router-link :to="`/item/${item.id}`" exact>
<v-img height="200" :src="item.img"></v-img>
<v-card-title>
<span style="margin:auto"> {{ item.title }} </span>
</v-card-title>
<v-card-text>
<div class="text-center">
<v-chip color="success" outlined class="pa-4">
<v-icon left>
fastfood
</v-icon>
{{ item.category }}
</v-chip>
</div>
</v-card-text>
</router-link>
Create a new Item.vue
file which will have the <Item>
component. Import it in Menu.vue
and register the component.
// Menu.vue
//Import component
import Item from "./Item.vue";
// Menu.vue
//Register component
components: {
Item
},
As per the API documentation, we can get the details of an individual item from its “id”. This id is passed to the “Menu.vue” component as a route parameter and is available when the component is created. We can save this as a data property. Also, create a method that fetches the product’s data when the component is created.
// Item.vue
//Life cycle hook - created
created(){
this.id = this.$route.params.id;
this.fetchItem();
},
// Item.vue
//Data properties
data: () => ({
id: null,
item: {},
addedToCart: false,
}),
As the name suggests fetchItem
method will get the item’s data and we will save the response in a data property called “product” which will be an object.
// Item.vue
//Fetch data
fetchItem(){
fetch(`https://my-json-server.typicode.com/adityaekawade/demo/menu/${this.id}`)
.then(res=>res.json())
.then(json=> this.item = json)
},
As per the tasks, we need to also create an “Add to order” button whose text is updated when it is clicked.
<!-- Item.vue -->
<v-btn color="#dd0031" style="color: white" block large>
<span @click="addToCart" v-if="!addedToCart">
Add to order
</span>
<span v-else>View order</span>
</v-btn>
Previously, we had added a data property addedToCart
. So if the addedToCart
is false, meaning, the item is not added to the order, the “Add to order button is displayed. Else if the addedToCart
is true, the text on the button is updated and it shows “View order”.
When “Add to order” button is clicked, it call the addToCart, which is defined below. For this exercise, it simply toggle the state of the data property addedToCart
to be true.
//Item.vue
addToCart(){
this.addedToCart = true;
}