How to Set Focus on an Input in Vue

Every now and then you'll need to programmatically focus on an input (or other element).

This is often needed for accessibility, or to make the app more convenient to use.

All browsers have a built-in method that let us focus on a specific element. But we need to get a hold of that element first.

In vanilla Javascript you would grab your element using something like this:

<form>
<input id="email" />
</form>
const input = document.getElementById('email');

But Vue 3 gives us a better way by using refs.

Let's see how this works in both the Composition API and the Options API.

Setting focus with the Composition API

First, we create a regular old ref:

<script setup>
import { ref } from 'vue';
const email = ref(null);
</script>

Then, we hook that ref up to our element by using the special ref attribute:

<template>
<input ref="email" />
</template>

Now, we just need to call the focus method on the element in order to focus on it:

<script setup>
import { ref } from 'vue';
const email = ref(null);
const focusInput = () => {
if (email.value) {
email.value.focus();
}
};
</script>

The email ref is a special kind of ref called a template ref, since it's linked to an element in our template.

Setting focus with the Options API

If you're using the Options API, it would look like this:

<template>
<input ref="email" />
</template>
const input = this.$refs.email;

Here we are using the special $refs object instead of creating ref variables.

Once we have our element, we can call focus on it:

<template>
<input ref="email" />
</template>
export default {
methods: {
focusInput() {
this.$refs.email.focus();
}
}
}

But what if you want to focus immediately when the component loads?

Set focus on page load

To do this, you'll want to call the focus method as soon as the component loads.

We'll need to make sure the element exists first, so we'll use the onMounted lifecycle hook:

<script setup>
import { ref, onMounted } from 'vue';
const email = ref(null);
const focusInput = () => {
if (email.value) {
email.value.focus();
}
};
onMounted(focusInput);
</script>

When using the Options API, this means we'll place the call in our mounted lifecycle hook:

<template>
<CustomInput ref="email" />
</template>
import CustomInput from './CustomInput.vue';
export default {
components: {
CustomInput,
},
mounted() {
this.focusInput();
},
methods: {
focusInput() {
this.$refs.email.$el.focus();
}
}
}