loading

Vue $emit()

We may construct a custom event in the child component that can be collected in the parent element using Vue’s built-in $emit() method.

Props are used for data transmission from the parent element to the child component; on the other hand, $emit() is used for data transfer from the child component back to the parent.

 

The aim of the subsequent actions is to make the food item’s “favorite” status change in the parent App.vue rather than the child component FoodItem.vue where it is now happening.

Because App.vue is where the favorite status is initially recorded, it needs to be updated, which is why it is being changed there rather than in FoodItem.vue. In a more extensive project, the data may originate from a database that we are connected to in App.vue. In order for a modification made from the component to affect the database, we must relay the changes made from the child component back to the parent.

Emit a Custom Event

Information must be sent from the component to the parent, and we achieve that by using the built-in $emit() method.

The FoodItem.vue component already contains the toggleFavorite function, which is called when the toggle button is pressed. We’re going to add a line to emit our custom event ‘toggle-favorite’ and remove the old line.

FoodItem.vue:

				
					methods: {
  toggleFavorite() {
    this.foodIsFavorite = !this.foodIsFavorite;
    this.$emit('toggle-Favorite');
  }
}
				
			

Although we are free to define the name of our own event, emit events often utilize kebab-case.

Receive an Emit Event

The ‘toggle-favorite’ custom emit event has now been released from the FoodItem.vue component; however, in order to observe that the event has occurred, we must listen for it in the App.vue parent and invoke a method that takes action.

Instead of using v-on to listen to the event, we use the shorthand @ in App.vue, the location where the component is created:

Example

Listen to the ‘toggle-favorite’ event in App.vue:

				
					<food-item
  v-for="x in foods"
  :key="x.name"
  :food-name="x.name"
  :food-desc="x.desc"
  :is-favorite="x.favorite"
  @toggle-favorite="receiveEmit"
/>
				
			

In order to be able to observe that our custom “toggle-favorite” event has occurred, we must first implement the receiveEmit method in App.vue:

				
					methods: {
  receiveEmit() {
    alert('Hello World!');
  }
}
				
			

Change The Food Item 'favorite' Status in The Parent

Now, when the ‘Favorite’ button from the child component is pressed, an event is triggered and App.vue is notified.

When a ‘Favorite’ button is selected, we want to modify the ‘favorite’ property for the appropriate food item in the ‘foods’ array in App.vue. Since the name of each food item is different, we transmit it from FoodItem.vue to App.vue in order to accomplish that:

FoodItem.vue:

				
					methods: {
  toggleFavorite() {
    this.$emit('toggle-favorite', this.foodName);
  }
}
				
			

Now, when the ‘toggle-favorite’ event occurs, the method called can accept the name of the food item in App.vue as an argument, as shown below:

Example

App.vue:

				
					methods: {
  receiveEmit(foodId) {  
    alert( 'You clicked: ' + foodId );
  }
}
				
			

We are now able to change the ‘favorite’ state for the appropriate food item within the ‘foods’ array as we know which food item was clicked:

App.vue:

				
					methods: {
  receiveEmit(foodId) {
    const foundFood = this.foods.find(
      food => food.name === foodId
    );
    foundFood.favorite = !foundFood.favorite;
  }
}
				
			

The ‘find’ array method in the code above searches the ‘foods’ array for an object whose name property matches the food item we clicked, returns that object as ‘foundFood’. Subsequently, we can configure ‘foundFood.health’ to be the inverse of its previous value, allowing it to alternate between true and false.

Discover more about the ‘find’ JavaScript array method here.

Find out more about arrow functions in JavaScript here.

The ‘favorite’ status of the appropriate food in the ‘foods’ array is now updated. The only thing required is to get the graphic representing preferred meal updated.

To change the picture, we simply need to refer to the ‘isFavorite’ prop in FoodItem.vue from v-show where the <img> element is, as the food item components are already constructed with the ‘favorite’ state from the ‘foods’ array and sent as a prop ‘sits-favorite’ from App.vue:

				
					<img decoding="async" src="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%200%200'%3E%3C/svg%3E" v-show="isFavorite" alt="Vue $Emit() -" title="Vue $Emit() 1" data-lazy-src="/img_quality.svg"><noscript><img decoding="async" src="/img_quality.svg" v-show="isFavorite" alt="Vue $Emit() -" title="Vue $Emit() 1"></noscript>
				
			

Since it is no longer in use, we can also remove the ‘foodIsFavorite’ data attribute from FoodItem.vue.

The 'emits' Option

Using the Vue ’emits’ option, we can describe what the FoodItem.vue component emits in the same manner that we specify props inside the component.

While emits are only advised to be documented, props need to be defined in the component.

We may record our emission in the FoodItem.vue component in this way:

				
					<script>
export default {  
  props: ['foodName','foodDesc','isFavorite'],
  emits: ['toggle-favorite'],
  methods: {
    toggleFavorite() {
      this.$emit('toggle-favorite', this.foodName);
    }
  }
};
</script>
				
			

Documenting the emits makes the component easier to utilize for others.

Share this Doc

Vue $emit()

Or copy link

Explore Topic