Fetch items from an API and display on a responsive frontend

This exercise will demonstrate how to fetch items from API (external) and display the response (menu items) in this example on a responsive frontend as shown in the prototype image.

Objective

Build a responsive web page that fetches items from API and formats and displays the response.

Description

The goal of this exercise is to build a page that looks similar to the prototype shown below.

Prototype of the menu page

Fetch items from an API and display

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 and fetch all items from API:

fetch("https://my-json-server.typicode.com/adityaekawade/demo/menu")
  .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"
    },{
    "id": 7,
    "title": "Chocolate smoothie",
    "img": "https://cdn.pixabay.com/photo/2015/11/23/11/54/chocolate-smoothie-1058191_960_720.jpg",
    "price": "3.75",
    "description": "Just simply delicious and refreshing. Made with high-quality chocolate and unsweetened cocoa powder, peanut butter, and vanilla extract. It is thick and creamy! ",
    "calories": "370",
    "proteins": "10",
    "category": "Drinks"
  }
]

 

Scenario:

We are building a page to display the menu items of the restaurant. We want to show the items in a grid layout. Primary information about the item such as its name, image, and category should be displayed. It is preferable to make this as a component so the same component can be reused at multiple places. If you have a layout created, it becomes easy to reuse the same component. Data is made available through an API.

 

Template:

You can use the following template to fork and get started:

https://codesandbox.io/s/fetchdisplayitemstemplate-uqh4e

Acceptance criteria

  • Fetch the items from an API
  • Display the items (preferably) in a grid layout
  • Show the item’s name, category, and image.
  • The webpage should be responsive
  • Use material design as a standard design practice

Hints

  • Use the native fetch function in javascript or library such as axios to get data from an API.
  • The REST endpoint for GET method is 'https://my-json-server.typicode.com/projectecode/demo/menu'
  • Use a design library such as bootstrap as a boilerplate for making responsive design

Solution Walkthrough

You can use the native fetch() function or a library such as axios to fetch the data from the API.

Example:

//Using fetch function

fetch("https://my-json-server.typicode.com/projectecode/demo/menu")
  .then((res) => res.json())
  .then((data) => {
    console.log(data);
  });

This should return a promise, once fulfilled, the response will be an array of objects that holds the menu items.

Store this response in a variable. Next, iterate through this data using a for loop and append the content to the HTML element.

You can use a framework such as bootstrap that will provide utilities to create a responsive layout.

The project is built in Vue.js and is bootstrapped using Vue CLI. Vue.js is a Javascript framework to build single-page applications. And Vue CLI provides a means for rapidly scaffolding the app.

Documentation: https://cli.vuejs.org/guide/creating-a-project.html#vue-create

Vuetify, a material design UI library, is installed as a plugin. Link: https://vuetifyjs.com/en/

Project structure

If you open the project folder, you will see a number of files and folders. The folder called public contains an HTML file, it’s this file that will serve our Vue App.

The package.json file is used to hold and manage all our dependencies.

src folder contains the files that create the application. Similar to React.js, Vue.js uses the concept of components. Every part of the UI in our application is a component. A main component App.vue is created when the project is bootstrapped with Vue CLI. You can nest the child components within App.vue.

Component Structure

A vue.js component is made up of the following three parts:

  • Template tag: This will serve as the HTML markup of the component
  • Script tag: You import other components, and write javascript in the script tag
  • Style tag: this holds the style of the component.

You can read more about the components basic here: https://vuejs.org/v2/guide/components.html

Components

Menu.vue file in the components/src directory is a component that is used to fetch and display the menu items.

data() function holds the local state of the component. A property menu_items is initialized as an empty array. This will hold the data which is fetched from the API.

   data: () => ({
     menu_items: [],
   }),

We will fetch the data when the component is created (using the created() lifecycle hook) using the fetch function. The data received is saved to the data property menu_items. If you log the response, you will notice that menu_items is an array of objects, where each object will be a menu item.

 created(){
   fetch('https://my-json-server.typicode.com/adityaekawade/demo/menu')
       .then(res=>res.json())
       .then(json=> {
         this.menu_items = json;
       });
  },

Next, we update our HTML to display the information we need from the data we’ve received.

Looping and rendering data

We use the v-for directive to render the menu items which is an array of objects. v-for ref: https://vuejs.org/v2/guide/list.html

<v-col v-for="(item, idx) in menu_items" :key="idx">
  . . . . . . . . .
</v-col>

Here, menu_items is the source data array, and item is an alias for the array element being iterated on:

Since each item is an object, its properties can be accessed using the dot (.) operator.

The item’s title can be displayed as shown above. using the “Mustache” syntax (double curly braces):

<span>{{ item.title }}</span>

The mustache tag will be replaced with the value of the item’s title property on the corresponding data object. It will also be updated If the object’s property changes.

Similarly, category can be displayed as

<span>{{ item.category }}</span>

However, mustaches cannot be used inside HTML attributes. So, Instead, use a v-bind directive Example for v-bind:

<!-- full syntax -->
<a v-bind:href="url"> ... </a>

<!-- shorthand -->
<a :href="url"> ... </a>

So the image attribute is added as:

<v-img :src="item.img"></v-img>

Ref: https://vuejs.org/v2/guide/syntax.html

Vuetify utilities are used to add material design. Example: <v-card> adds creates a material design card in the layout. Follow the links to read about the vuetify utilities: