Home > Software engineering >  Vue 3, where to listen for emit event
Vue 3, where to listen for emit event

Time:04-01

I'm sending an event from a child component to my parent component using $emit. I know I should tell the parent component to listen to that event, however I don't know where to put the

@openModal="changeModalVisibility"

Should I do it as an attribute in the main div? Since this is the highest component I don't find the right place.

Child:

<template>
  <div  v-on:click="openModal">
    <img :src="cocktailImg" alt="cocktail-image" />
    <p>{{ cocktailName }}</p>
    <div >
      <img
        src="../assets/img/arrow-forward-icon.svg"
        alt="arrow icon"
        
      />
    </div>
  </div>
</template>

<script>
export default {
  name: "CocktailResult",
  props: {
    cocktailName: {
      type: String,
    },
    cocktailImg: {
      type: String,
    },
    modalClass: {
      type: String,
    },
  },
  methods: {
    openModal() {
      this.$emit("openModal");
    },
  },
};
</script>

Parent:

<template>
  <div  v-on:openModal="changeModalVisibility">
    <div >
      <img src="./assets/img/logo.png" alt="logo"  />
      <div >
        <input
          type="text"
          v-model="searchQuery"
          
          placeholder="Enter Your Favorite Cocktail:"
          @input="callCocktailApi"
        />
        <img
          src="./assets/img/close-icon.svg"
          alt="close icon"
          
          v-on:click="clearInput"
        />
      </div>
    </div>
    <div >
      <ul v-for="(cocktail, index) in cocktailArray" :key="cocktail.key">
        <CocktailResult
          :cocktailName="this.cocktailArray[index].strDrink"
          :cocktailImg="this.cocktailArray[index].strDrinkThumb"
          :cocktailGlass="this.cocktailArray[index].strGlass"
          :cocktailInstructions="this.cocktailArray[index].strInstructions"
          :modalClass="this.modalClass"
          :method="changeModalVisibility"
        />
      </ul>
    </div>
    <CocktailModal :modalClass="this.modalClass" />
  </div>
</template>

<script>
import CocktailResult from "./components/CocktailResult.vue";
import CocktailModal from "./components/CocktailModal.vue";
import axios from "axios";

export default {
  name: "App",
  data() {
    return {
      cocktailArray: "",
      searchQuery: "",
      cocktailName: "",
      cocktailImg: "",
      modalClass: "hidden",
    };
  },
  components: {
    CocktailResult,
    CocktailModal,
  },
  methods: {
    callCocktailApi() {
      axios
        .get(
          `https://www.thecocktaildb.com/api/json/v1/1/search.php?s=${this.searchQuery}
    ` // API Call
        )
        .then((res) => {
          this.cocktailArray = JSON.parse(
            JSON.stringify(res.data.drinks || [])
          );

          this.cocktailName = this.cocktailArray[0].strDrink;

          // Only render results if an array is fetched

          console.log(this.cocktailArray);
        })
        .catch((error) => {
          console.log(error);
        });
    },

    clearInput() {
      this.cocktailArray = "";
      this.searchQuery = "";
    },

    changeModalVisibility() {
      this.modalClass = "";
      console.log("I'm working");
    },
  },
};
</script>

CodePudding user response:

You should put @openModal in your parent component, there were you call CocktailResult.

<CocktailResult 
 @openModal=“YourCallback”
 … 
/>
  • Related