0

Hello Im doing a simple cocktailapp to practice nuxt.js and axios with coktailDB API https://www.thecocktaildb.com/api.php. In drinks/index.vue I have listed all drinks with v-for. When clicking on a drink you get to drinks/_id/index.vue page where the full info about the drink will get showed by its ID. Im using $route.params.id and I have tried with this.$route.params.id. No drink info get showed. Its just shows undefined and brackets. How can I get the drink info to be showed by its ID after been clicking on a specific drink? Thanks in advance!

Drinks/index.vue;

<template>
  <div>
  <div>
    <SearchDrink/>
  </div>
  <div>
  <div v-for="drink in drinks" :key="drink.id"> 
  <nuxt-link :to="'drinks/' + id">
    <div class="drink">
    <p> {{ drink.strDrink
    }} </p>
    <img :src="drink.strDrinkThumb" alt=""/> 
    <p>Instructions:</p>
    <p> {{ drink.strInstructions }} </p>
    <div class="ing"> Ingridients: 
      <ul>
        <li>{{ drink.strIngredient1 }} </li>
        <li>{{ drink.strIngredient2 }} </li>
        <li>{{ drink.strIngredient3 }} </li>
        <li>{{ drink.strIngredient4 }} </li>
        <li>{{ drink.strIngredient5 }} </li>
      </ul>
  </div>
  </div>
</nuxt-link>
</div>
</div>
</div>
</template>

<script>
import SearchDrink from '../../components/SearchDrink.vue'
import axios from 'axios'

export default {
  components:{
    SearchDrink,
  },
  data(){
    return {
      drinks: [],
    }
  },
 methods: {
    getAllDrinks(){
      axios.get('https://thecocktaildb.com/api/json/v1/1/search.php?s=')
      .then((response) => {
        this.drinks = response.data.drinks
        const myDrink = response.data.drinks
        console.log(myDrink)
        console.log(myDrink.strDrinkThumb)  
        })
    .catch((error) =>{
      console.log(error)
    })
    
    }, 
 },
  created(){
    this.getAllDrinks()
  },
  // methods: {
  //   searchDrink(){
  //     if(!this.search){
  //       return this.drinks
  //     }else{
  //       return this.drinks.filter(drink => 
  //       drink.text.toLowerCase().includes(this.search.
  //       toLowerCase()))
  //     }
  //   }
  // },
    head(){
        return {
            title: 'Drinks App',
            meta: [
                {
                    hid: 'description',
                    name: 'description',
                    content: 'Best place to search a Drink'
                }
            ]
        }
    }
}
</script>

Drinks/_id/index.vue;

<template>
  <div>
    <nuxt-link to="/drinks">
        Go Back
    </nuxt-link>
    <h2> {{ drink }} </h2>
    <hr>
    <small>Drink ID: {{ this.$route.params.id }}</small>
  </div>
</template>

<script>
import axios from 'axios'

export default {
    data(){
        return{
            drink: {}
        }
    },
    methods: {
    getAllDrinks(){
      axios.get(`www.thecocktaildb.com/api/json/v1/1/lookup.php?i=${this.$route.params.id}`)
      .then((response) => {
        this.drinks = response.data.drinks
        const myDrink = response.data.drinks
        console.log(myDrink) 
        })
    .catch((error) =>{
      console.log(error)
    })
    
    }, 
 },
  created(){
    this.getAllDrinks()
  },
  head(){
        return {
            title: this.drink,
            meta: [
                {
                    hid: 'description',
                    name: 'description',
                    content: 'Best place to search a Drink'
                }
            ]
        }
    }
}
</script>

enter image description here

enter image description here

kissu
  • 40,416
  • 14
  • 65
  • 133
tocajossan
  • 41
  • 9

1 Answers1

1

There are quite a few things that be improved here (and the API is a bit messy too).
Here is how I would do it with modern practices.

/pages/drinks/index.vue

<template>
  <div>
    <div v-for="drink in drinks" :key="drink.idDrink">
      <nuxt-link :to="`/drinks/${drink.idDrink}`">
        <div class="drink">
          <p>{{ drink.strDrink }}</p>
          <img width="100px" height="100px" :src="drink.strDrinkThumb" alt="" />
          <p>Instructions:</p>
          <p>{{ drink.strInstructions }}</p>
          <div class="ing">
            <p>Ingredients:</p>
            <ul>
              <li>{{ drink.strIngredient1 }}</li>
              <li>{{ drink.strIngredient2 }}</li>
              <li>{{ drink.strIngredient3 }}</li>
              <li>{{ drink.strIngredient4 }}</li>
              <li>{{ drink.strIngredient5 }}</li>
            </ul>
          </div>
        </div>
      </nuxt-link>
    </div>
  </div>
</template>

<script>
import axios from 'axios'

export default {
  data() {
    return {
      drinks: [],
    }
  },
  async fetch() {
    await this.getAllDrinks()
  },
  methods: {
    async getAllDrinks() {
      try {
        const { data } = await axios.get(
          'https://thecocktaildb.com/api/json/v1/1/search.php?s='
        )
        this.drinks = data.drinks
      } catch (error) {
        console.log('error', error)
      }
    },
  },
}
</script>

/pages/drinks/_id.vue

<template>
  <div>
    <nuxt-link to="/drinks"> Go Back </nuxt-link>
    <h2>{{ drink.strGlass }}</h2>
    <hr />
    <small>Drink ID: {{ $route.params.id }}</small>
  </div>
</template>

<script>
import axios from 'axios'

export default {
  data() {
    return {
      drink: {},
    }
  },
  async fetch() {
    await this.getAllDrinks()
  },
  methods: {
    async getAllDrinks() {
      try {
        const { data } = await axios.get(
          `https://www.thecocktaildb.com/api/json/v1/1/lookup.php?i=${this.$route.params.id}`
        )
        this.drink = data.drinks[0]
      } catch (error) {
        console.log('error', error)
      }
    },
  },
}
</script>

Few notes:

  • I skipped the parts I don't have access to (like your SearchDrink component) or that are not relevant with the current issue
  • you probably would need to use the axios module
  • you don't need to import your Nuxt components, it is done for you
kissu
  • 40,416
  • 14
  • 65
  • 133
  • Thank you for your answer! I get now the Id correctly when clicking on a drink and coming in to _id/index.vue. That works but if I want to show more details do I need to use axios and fetch the API again like in drinks/index.vue. I have added the searchDrink also. Thank you. – tocajossan Dec 08 '22 at 11:45
  • @tocajossan looking at the API, if you want to get all the details you indeed need to do that for the `_id` page. Depends on the number of details you need overall. – kissu Dec 08 '22 at 13:24
  • Okey I have now added the search API to get the details, but now I get all details for all drinks, because I use a v-for. How can I only get the details for the drink I clicked? – tocajossan Dec 08 '22 at 14:27
  • @tocajossan my answer is already explaining that. Hence the `_id.vue` file, details for a specific drink, `index.vue` for all drinks. – kissu Dec 08 '22 at 14:38