{{announcement.body}}
{{announcement.title}}

Vue Tutorial 8 — Component Events

DZone 's Guide to

Vue Tutorial 8 — Component Events

In this article, we discuss how to handle communication between parent and child components in Vue.js.

· Web Dev Zone ·
Free Resource

In our pursuit of being able to handle large, scalable, maintainable web apps we became familiar with and learned about Vue Components. We learned how to:

  • Define a component.
  • Instantiate a component.
  • Pass data to a component using props.

In this tutorial, we’ll learn how to trigger events in the app based on some user action registered by our “child” component. 

Component Events

As we build out the blog feature, it may become necessary for our “child” components to communicate back to the “parent” app. For example, we may decide to include a feature to vote on comments. Let’s implement this now, and we’ll start by adding a button to the user-comment component from the previous tutorial

JavaScript




x


 
1
Vue.component('user-comment', {
2
    props: ['comment'],
3
    template: `<div class="my-5">
4
                    <p class="font-weight-bold">{{ comment.name }} said:</p>
5
                    <p>{{ comment.content }}</p>
6
                    <i class="far fa-thumbs-up"></i>
7
                </div>`
8
})



The above component employs a template literal to allow our template to be more readable and span across multiple lines, rather than being written in a single line. 


Image title

Example output

Our most immediate problem right now is the fact that nothing happens when the thumbs up icon is pressed. Let's fix this.

The parent app has the ability to listen to a particular event on a component:

JavaScript




xxxxxxxxxx
1


 
1
 <user-comment
2
                v-for="comment in comments"
3
                v-bind:comment="comment"
4
                v-bind:key="comment.id"
5
                v-on:thumbs-up="thumbsUp"
6
        >
7
        </user-comment>



When the component triggers a thumbs-up event, we will then call the  thumbsUp method, which we must implement in the app:

JavaScript




xxxxxxxxxx
1


 
1
methods: {
2
    thumbsUp: function () {
3
        console.log("thumbsup pressed")
4
    }
5
}



With the parent listening for a child’s thumbsUp event, we must now trigger this event on icon click. To achieve this we will emit an event using the $emit method

You may also like: How and Why We Moved to Vue.js.
JavaScript




xxxxxxxxxx
1


 
1
Vue.component('user-comment', {
2
    props: ['comment'],
3
    template: `<div class="my-5">
4
                    <p class="font-weight-bold">{{ comment.name }} said:</p>
5
                    <p>{{ comment.content }}</p>
6
                    <i class="far fa-thumbs-up" v-on:click="$emit('thumbs-up')"></i>
7
                </div>`
8
})



Image title

Listening for thumbsUp event

As you can see, the  thumbsUp method gets triggered when the icons is pressed. We have successfully emitted an event from the child component to the parent. How about passing some data from the child to the parent? Let’s pass the comments id so the parent can know which comments should receive the new like. 

JavaScript




xxxxxxxxxx
1


1
<i class="far fa-thumbs-up" v-on:click="$emit('thumbs-up', comment.id)"></i>



You can adjust the parents thumbsUp method to show us what’s being passed from the child

JavaScript




xxxxxxxxxx
1


 
1
thumbsUp: function (event) {
2
    console.log(`thumbsup pressed ${event}`)
3
}



Don't forget to pass this event, as per below code block

JavaScript




xxxxxxxxxx
1


1
<user-comment
2
                v-for="comment in comments"
3
                v-bind:comment="comment"
4
                v-bind:key="comment.id"
5
                v-on:thumbs-up="thumbsUp($event)"
6
        >
7
        </user-comment>



As you can see in the screenshot below, we now receive the id of the comment that was liked!

Image title

Notification that comment was liked

To update a comment's number of likes, we must naturally first add that property to our comments starting with a default value of 0

JavaScript




xxxxxxxxxx
1


 
1
comments: [
2
    {id: 1, name: "Jerry", content: "I love Vue so much", likes: 0},
3
    {id: 2, name: "Eric", content: "Vue.js solved all my relationship problems!", likes: 0},
4
    {id: 3, name: "Sandra", content: "I'm currently on the beach coding Vue as we speak!", likes: 0},
5
]



Now, we can search the comments array by id and increment the number of likes

JavaScript




xxxxxxxxxx
1
12


 
1
 methods: {
2
    thumbsUp: function (commentId) {
3
        console.log(`thumbsup pressed ${commentId}`)
4
 
          
5
        let comment = this.comments.find(x => x.id === commentId)
6
        if (comment != undefined) {
7
            comment.likes += 1;
8
        } else {
9
            console.log("Comment not found")
10
        }
11
    }
12



To ensure that our “Like” mechanism works, let’s display the number of likes next to the icon inside the child component

JavaScript




xxxxxxxxxx
1


 
1
{{ comment.likes }} <i class="far fa-thumbs-up" v-on:click="$emit('thumbs-up', comment.id)"></i>



If you followed the tutorial correctly, you now have a working comment-like mechanism that looks like the following

Image title

Final output

Conclusion

In this tutorial, you’ve learned how to handle component events and how to literally “emit” them to the parent. This is a feature that I think you'll use quite often. As a challenge, I would suggest that you also implement a dislike button that decrements the number of likes for each comment following the methods you’ve learned today. 

The code for this tutorial is available here.

Note: You can find parts onetwothreefourfivesix and seven of this series at their respective links. 


Further Reading

Topics:
vuejs 2 ,vuejs 2 tutorial ,components ,events ,javascript ,template literals ,web dev ,tutorial

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}