How to Set Focus on an Input in Vue

To set focus on an input in Vue:

  1. Set a ref on the input element.
  2. Access the new ref from the $refs property of the Vue instance.
  3. Call the focus() method on the ref element object.

Set focus on input on button click

For example:

App.js

<template>
  <div id="app">
    <input
      ref="name"
      placeholder="Name"
    />{{ ' ' }}
    <button @click="focusInput">Focus</button>
  </div>
</template>

<script>
export default {
  methods: {
    focusInput() {
      this.$refs.name.focus();
    },
  },
};
</script>
Clicking the button sets focus on the input.
Clicking the button sets focus on the input.

First, we create a new Vue instance ref by setting the input ref prop to a value (name).

<input
  ref="name"
  placeholder="Name"
/>

After doing this, we are able to access the $refs property of the Vue instance to access the object that represents the input element. We then call the focus() method on this object to set focus on the input.

this.$refs.name.focus();

We set the focusInput() method as a handler for the click event of the Focus button. So when the button is clicked, focusInput() is called and the input gains focus.

<button @click="focusInput">Focus</button>

Set focus on custom input component

Custom input components are useful for abstracting logic built around an input element and for reusing an input element styled in a particular way.

For custom components, calling focus() on its ref object will cause an error. For it to work, we’ll need to add a focus() method to the custom component that calls the focus() method of its root input element.

For example:

components/CustomInput.vue

<template>
  <input
    placeholder="Name"
    class="custom-input"
    ref="input"
  />
</template>

<script>
export default {
  methods: {
    // 👇 Create custom "focus" method
    focus() {
      this.$refs.input.focus();
    },
  },
};
</script>

<style scoped>
.custom-input {
  font-family: 'Segoe UI';
  font-weight: bold;
  font-size: 16px;
  color: blue;
  height: 30px;
  width: 200px;
}
</style>

App.js

<template>
  <div id="app">
    <custom-input ref="name"></custom-input>
    <br />
    <br />
    <button @click="focusInput">Focus</button>
  </div>
</template>

<script>
import CustomInput from './components/CustomInput.vue';

export default {
  methods: {
    focusInput() {
      // 👇 call custom "focus" method
      this.$refs.name.focus();
    },
  },
  components: { CustomInput },
};
</script>

Now we can set focus on the custom input component when the button is clicked.

Clicking the button sets focus on the custom input component.
Clicking the button sets focus on the custom input component.

Set focus on input after page load

To give the input focus immediately after the page loads, we can call the focus() method from the mounted lifecycle hook of the Vue instance with the input ref. The mounted method is called after a component is added to the DOM, which happens when a page is loading.

For example:

App.js

<template>
  <div id="app">
    <input
      ref="name"
      placeholder="Name"
    />
  </div>
</template>

<script>
export default {
  mounted() {
    this.focusInput();
  },
  methods: {
    focusInput() {
      this.$refs.name.focus();
    },
  },
};
</script>
The input gains focus after the page loads.
The input gains focus after the page loads.

Set focus on input after re-render

There are scenarios where we’ll need to wait for the DOM to be updated before calling focus() to give the input element focus.

For example, we might be using a boolean variable to determine whether an input element should be present in the DOM or not.

Because Vue batches state updates, the input element might not be added to the DOM immediately, and we won’t be able to access its ref right away.

We can use the nextTick() instance method to ensure that the DOM has been updated to include the input after modifying the boolean variable before calling focus().

<template>
  <div id="app">
    <!-- 👇 conditional rendering with "v-if" directive -->
    <input
      v-if="showInput"
      ref="name"
      placeholder="Name"
    />
    <br /><br />
    <button @click="focusInput">Show and focus</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      showInput: false,
    };
  },
  methods: {
    focusInput() {
      // 👇 Set boolean variable to show input
      this.showInput = true;

      this.$nextTick(() => {
        // This callback will only be called after the
        // DOM has been updated
        this.$refs.name.focus();
      });
    },
  },
};
</script>
The input gains focus after the DOM is updated to include it.
The input gains focus after the DOM is updated to include it.

Set focus on next input after Enter press

Let’s say we have multiple input elements that need to be filled on the page. We could improve the UX by focusing on the succeeding text input when the user presses the Enter key to signify that they are done with filling in one input.

We do this by assigning a listener to the keypress event on the first input. Because of the enter event modifier, the event listener is only called when a key is pressed and the key is Enter.

We create a ref for the second input, and in the keypress.enter event listener we call the focus() method on the ref object to set focus on the second input.

<template>
  <div id="app">
    <form>
      <input
        placeholder="1st name"
        @keypress.enter="focusName2"
      />
      <br /><br />
      <input
        ref="name2"
        placeholder="2nd name"
      />
    </form>
  </div>
</template>

<script>
export default {
  methods: {
    focusName2() {
      this.$refs.name2.focus();
    },
  },
};
</script>
Pressing Enter sets focus on the next input.
Pressing Enter sets focus on the next input.



11 Amazing New JavaScript Features in ES13

This guide will bring you up to speed with all the latest features added in ECMAScript 13. These powerful new features will modernize your JavaScript with shorter and more expressive code.

11 Amazing New JavaScript Features in ES13

Sign up and receive a free copy immediately.

Leave a Comment

Your email address will not be published. Required fields are marked *