Handling Events with Vue.js
Tags: vue, events
Published: 2020-01-06 00:00:00

---
layout: post
title:  Handling Events with Vue.js
description: "If a user clicks a button, submits a form, or even just moves their mouse, you can get your Vue site to respond by using the events system."
date: 2020/01/06
published: true
tags: [vue.js,events]
cover_image: https://vuejsdevelopers.com/images/posts/versions/generic_vue_header_1200.webp
code: hev
level: beginner
ad: ev 
---

When you build a dynamic website with Vue you'll most likely want it to be able to respond to *events*.

For example, if a user clicks a button, submits a form, or even just moves their mouse, you may want your Vue site to respond somehow. 

*Note: this article was originally posted [here on the Vue.js Developers blog](https://vuejsdevelopers.com/2020/01/06/handling-events-vue-js?utm_source=devto&utm_medium=article&utm_campaign=hev) on 2020/01/06.*

## Handling events with Vue

We can intercept an event by adding the `v-on` directive to the relevant DOM element. Let's say we want to handle a click on a button element - we can add the following to our Vue template:

```html
<button v-on:click="clickHandler"></button>
```

Note that we add an *argument* to the `v-on` directive, which will be the name of the event we want to handle (in this case, `click`).

We then bind an expression to the directive, which will normally be a method you want to use to handle the event. In this case, we've called it `clickHandler`.

> Tip: the `v-on` directive has a convenient shorthand `@` that can be used instead of `v-on:` like this: `<button @click="clickHandler"></button>`.

## Types of events you can handle

Besides `click`, what other DOM events can be handled? Vue can handle any kind of web or mobile native event (as well as custom events which we'll talk about later) including:

- submit
- keyup
- drag
- scroll

And more. [Here's a list](https://en.wikipedia.org/wiki/DOM_events#Common_events) of the most common DOM events for your reference.

## Event handling methods

If we bind a method to our event handling directive we can now run some custom code.

Let's keep it simple in this example and just log a message to the console, but you could also do something more interesting like show/hide another element, increment a counter, etc.

```html
<div id="app">
  <button v-on:click="clickHanlder"></button>
</div>
```

```js
new Vue({
  el: "#app",
  methods: {
    clickHandler () {
      console.log("You clicked the button!");
    }
  }
})
```

## Event object

An `event` object gets passed to your event handler which opens more possibilities for how you can respond to an event. This object contains a lot of useful properties and methods including a reference to the element where the event originated (`event.target`), the time the event occurred (`event.timeStamp`) and more.

```js
clickHandler (event) {
  console.log(`The button was clicked at ${event.timeStamp}.`);
}
```

Note that this object is provided by the native Web API, not Vue, so it will be the same object you'd find in pure JavaScript. Here's the [event interface reference](https://developer.mozilla.org/en-US/docs/Web/API/Event) for your convenience.

## Event modifiers

A common pattern in JavaScript apps is to handle a form submit manually rather than using the native functionality. To do this, you need to use the native `preventDefault` method of the submit event before running your form handling code, otherwise the page will be redirected before it has a chance to complete.

```js
formHandler (event) {
  event.preventDefault();
  // form handling logic
}
```

Rather than doing this manually in your handler, Vue offers an event *modifier* to do this directly from the template. Note the modifier is added after the `.` in the directive:

```html
<form @submit.prevent="formHandler"></form>
```

Vue offers several different event modifiers that are useful in common event handling scenarios:

- `.stop`
- `.prevent`
- `.capture`
- `.self`
- `.once`
- `.passive`

<content-ad/>

## Custom events

So far we've been talking about handling *native* events. But Vue is a component-based framework, so could we make a component emit its own event?

Yes, and this can be very useful. Let's say want a *child* component to send data up to a *parent* component. We can't use props here, as prop data only goes from parent to child, and not the other way.

```
ParentComponent
 |
 | (data travels down via props, never up)  
 v 
ChildComponent
```

The solution is to have the child component emit an event, and have the parent listen to it.

To do this, call `this.$emit("my-event")` from the child component when you want the event to be emitted. For example, say we have a component *DialogComponent* that needs to inform it's parent *MainPage* that it has been closed:

*DialogComponent*

```js
export default {
  methods: {
    onClose() {
      this.$emit("dialog-closed");
    }
  }
};
```

The parent component can then handle the custom event exactly the same as it would a native event.

*MainPage*

```html
<div>
  <dialog-component @dialog-closed="eventHandler" />
</div>
```

You can also send data in your custom event which can be received in the handling method:

*DialogComponent*

```js
onClose() {
  this.$emit("dialog-closed", { time: Date.now() });
}
```

*MainPage*

```js
eventHandler (event, { time }) {
  console.log(`Dialog was closed at ${time}`);
}
```

> Tip: use *kebab-case* names for your custom events! HTML is case-insensitive, so a camel-case event name e.g. `myEvent` will, confusingly, be `myevent` in the template. So it's best to use kebab-case e.g. `my-event` and avoid confusion.

## Event bus

As we've seen above, a *child* component can send an event to a *parent* component. But what if you want a component to send an event to *any other* component in the hierarchy? For example, a sibling, grand-parent, etc.

To achieve this we can use a pattern called *event bus*. This is where we create a separate instance of Vue to transport an event to any component that imports it.

First, create and export a Vue instance in a new module file:

*eventBus.js*

```js
import Vue from "vue";
export default new Vue();
```

Next, import the bus into a component where you would like to *emit* an event. You can use the `$emit` method of you bus Vue instance. 

```js
import eventBus from "./eventBus";

export default {
  ...
  methods: {
    myMethod () {
      eventBus.$emit("my-event")
    }
  }
}
```

Finally, import the bus into a component where you would like to *listen* to the event. You should then set up a listener somewhere in your code. I suggest you use a lifecycle hook like `created` as you can access the component instance here. 

This is done with the `$on` method of the bus which takes two arguments - the event you want to listen for, and a callback.

```js
import eventBus from "./eventBus";

export default {
  ...
  created () {
    eventBus.$on("my-event", () => {
      console.log("my-event called on global event bus");
    });
  }
}
```

And there you have it - a way to share data between any components in your app!

> Tip: a more scalable solution for passing data around an app is to use [Vuex](https://vuejsdevelopers.com/2017/05/15/vue-js-what-is-vuex).

* * *

**Enjoy this article?**

Get more articles like this in your inbox weekly with the *Vue.js Developers Newsletter*.

[Click here to join!](https://vuejsdevelopers.com/newsletter?utm_source=devto&utm_medium=article)

* * *