The url to fetch data is https://forkify-api.herokuapp.com/api
We get GET data like so:
https://forkify-api.herokuapp.com/api/search?q=pizza
https://forkify-api.herokuapp.com/api//get?rId=47746
src/js/models/Search.js
We use Axios library for data fetching:
1) We await the Promise object to be done
2) then we extract the status to make sure its all OK
3) we finally log the result
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
import axios from 'axios' export default class Search { constructor(query) { this.query = query this.result = null } async getResults() { try { const res = await axios(`https://forkify-api.herokuapp.com/api/search?q=${this.query}`); const {status, statusText} = res if (status === 200 && statusText === 'OK') { this.result = res.data && res.data.recipes; console.log(this.result) } } catch (err) { console.log(err) } } } |
The default http grammar is GET. axios(…) automatically use this if we only give it an url.
We will be using this Search’s getResults in the view. However, we need to set up utility functionality first.
src/js/views/base.js
This is just a way to get the DOM element of a certain class or id. Typically, we use document.querySelector, and then we store it in a literal object like so:
1 2 3 4 5 |
export const elements = { searchForm: document.querySelector('.search'), searchInput: document.querySelector('.search__field'), searchResList: document.querySelector('.results__list') } |
Once we get the DOM element, we can use textContent, innerText, innerHTML to get the content.
src/js/views/searchView.js
The whole point to this searchView is to create a renderResults function that our controller can use.
We implement a renderResults function that outputs HTML for rending the content. We render the content. It takes in an recipe object and then uses the object’s properties along with the HTML. We also shorten the incoming titles to the length we want by using reduce.
Other purpose is to clear textfields and such:
– clearResults
– clearInputs
We first import the base. Then we simply access value, or innerHTML, according to what we want. From there we can clear certain HTML controls.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
import { elements } from './base' export const getInput = () => elements.searchInput.value; export const clearInput = () => { elements.searchInput.value = ''; } export const clearResults = () => { elements.searchResList.innerHTML = ''; } const limitRecipeTitle = (title, limit = 17) => { const newTitle = []; if (title.length > limit) { title.split(' ').reduce((acc, cur) => { if (acc + cur.length <= limit) { newTitle.push(cur) } return acc + cur.length; }, 0); return `${newTitle.join(' ')}` } return title } const renderRecipe = receipe => { const markup = `<li> <a class="results__link results__link--active" href="#${receipe.recipe_id}"> <figure class="results__fig"> <img src="${receipe.image_url}" alt="${limitRecipeTitle(receipe.title)}"> </figure> <div class="results__data"> <h4 class="results__name">${limitRecipeTitle(receipe.title)}</h4> <p class="results__author">${receipe.publisher}</p> </div> </a> </li>`; elements.searchResList. insertAdjacentHTML('beforeend', markup) } export const renderResults = recipes => { recipes.forEach(recipe => renderRecipe(recipe)) } |