Vue

How to use Vue Template Refs to Access HTML Elements

Sponsor

Vue gives us a lot of powerful features when it comes to manipulating the DOM. It simplifies the job of maintaining states, to create UIs which are easy to maintain, and fun to use. One thing Vue does really well, is removes the need for direct DOM manipulation. Sometimes, though, we still need to manipulate or reference DOM elements themselves. Fortunately, Vue has thought of this, and allows us to do this with the ref attribute. We'll cover how you can do this with the Options API, and then with the Composition API.

Referencing DOM Elements in Vue

Although it's certainly possible to use .querySelector() on a Vue document, it's not best practice. If we want to reference a DOM element, we can use the ref attribute in Vue.

Let's look at a quick example. Below, we have our App.vue page, which has an input, and we want to reference that input directly in one of our methods:

<template> <button id="myButton">Some Button</button> </template> <script> export default { mounted: function() { } } </script>

Vue can store references to DOM elements in a property called $ref. The first thing we have to do, is add a ref attribute to the element we want to reference in our Javascript. The value of the ref attribute will be the name of it within the $ref property.

For mine, I am calling it myButton:

<template> <button id="myButton" ref="myButton"></button> </template>

Next, in our Javascript, we can call upon that reference, as shown below:

export default { mounted: function() { console.log(this.$ref.myButton); }

This will return the DOM element itself - so you can manipulate it like you'd manipulate any DOM element.

How to use Vue references to return a DOM element

Referencing Child Components

If our button was a component, we could also access it using the same ideas. For example suppose we have a child component, called TestComponent. We can add a ref directly to the child component, as shown below:

<template> <button id="myButton" ref="myButton">Some Button</button> <TestComponent ref="anotherButton" /> </template> <script> import TestComponent from '../components/TestComponent.vue'; export default { components: { TestComponent }, mounted: function() { // Console logs our "myButton" console.log(this.$refs.myButton); // Console logs "anotherButton" console.log(this.$refs.anotherButton); } } </script>

Above, we add ref to the component itself:

<TestComponent ref="anotherButton" />

The difference here, is that it doesn't return the DOM element itself - it instead returns an object for the child component.

Returning a child component using Vue references

Referencing a Child Component's DOM element

Since we get an object for a child component when using references, if we want to access the DOM element within a child component itself, we have to use $el - which will refer to the DOM element in the component itself.

// This is the child component reference this.$refs.anotherButton // This is the DOM element for the component this.$refs.anotherButton.$el

Referencing a Child Component's Method

Since a referencing a child component refers to the entire component, we can reference its methods using this reference. Let's say our child component has Javascript that looks like the code below.

TestComponent.vue

<script> export default { methods: { someFunction: function() { console.log('Hello'); } } } </script>

In our main, App.vue file, we can reference this method through our reference. For example:

<template> <button id="myButton" ref="myButton">Some Button</button> <TestComponent ref="anotherButton" /> </template> <script> import TestComponent from '../components/TestComponent.vue'; export default { components: { TestComponent }, mounted: function() { this.$refs.anotherButton.someFunction(); } } </script>

Above, since we have added a reference ref="anotherButton" to the child component, we can reference it in our Javascript through that reference. All methods are available through this reference:

this.$refs.anotherButton.someFunction();

Composition API - Using Template Refs

Things are a little different if you are using the composition API. In this case, we don't have access to the this.$refs object. So instead we need to define a variable to hold our ref. For example, if I wanted to access the input element below using a ref with the composition API, I have to do this:

<script setup=""> import { ref, onMounted } from 'vue' const myInput = ref(""); onMounted(() => { console.log(myInput.value); }) </script> <template> <input ref="myInput"> </template>

Above, we have an input with the ref myInput. We define a variable in our setup script called myInput which holds a ref function. Now when onMounted fires and the HTML code has loaded, we can access the DOM element referenced via myInput.ref.

Using References with v-for

The same concepts apply to v-for. If you use a ref on a v-for element, each element produced by the v-for loop, will be returned as an array within that reference.

For example, let's say we have the following code:

<template> <ul> <li v-for="(item, index) in locations" :key="index" ref="myLocations">{{ item.name }}</li> </ul> </template> <script> export default { data() { return { locations: [ { name: 'London', date: '11/02/2022' }, { name: 'Paris', date: '12/01/2022' }, { name: 'Tokyo', date: '04/06/2021' } ] } }, mounted: function() { let liElements = this.$refs.myLocations; console.log(liElements); } } </script>

Since we've added a ref called myLocations to our li element, we can now access it via this.$refs.myLocation. Since it is also a v-for, myLocation will be an array. To get the second li element, we would do the following:


this.$refs.myLocations[1];

Conclusion

References in Vue are a powerful way to access the DOM elements that Vue produces. They are also the best way to do it when working within the Vue framework. I hope you've enjoyed this article. For more Vue content, you can find it here.

Last Updated Thursday, 24 March 2022
Johnny Simpson
Johnny Simpson

More Tips and Tricks Vue

Subscribe for Weekly Dev Tips

Subscribe to our weekly newsletter, to stay up to date with our latest web development and software engineering posts via email. You can opt out at any time.

Not a valid email