DEV Community

Ibrahim
Ibrahim

Posted on

How to Access an Element Inside a Child Component in Vue

Suppose there is a BaseInput.vue component that contains an input element:

<!-- BaseInput.vue -->
<template>
  <input type="text">
</template>
Enter fullscreen mode Exit fullscreen mode

The BaseInput.vue component is used inside App.vue:

<!-- App.vue -->
<script setup>
import BaseInput from './components/BaseInput.vue';
</script>

<template>
  <BaseInput />
</template>
Enter fullscreen mode Exit fullscreen mode

In App.vue, we can't directly access the input element inside the BaseInput component using ref, it only provides access to the component instance properties.

For example, if we try to focus the input, it will cause an error:

<!-- App.vue -->
<script setup>
import { ref, onMounted } from 'vue'
import BaseInput from './components/BaseInput.vue';

const baseInputEl = ref()

onMounted(() => {
  baseInputEl.value.focus() // Uncaught TypeError: baseInputEl.value.focus is not a function
})
</script>

<template>
  <BaseInput ref="baseInputEl" />
</template>
Enter fullscreen mode Exit fullscreen mode

To fix this, we can expose the input element inside the BaseInput component using the defineExpose function.

<!-- BaseInput.vue -->
<script setup>
import { ref } from 'vue';

const inputEl = ref()

defineExpose({
  inputEl
})
</script>

<template>
  <input type="text" ref="inputEl">
</template>
Enter fullscreen mode Exit fullscreen mode

Now, when we access the ref of the BaseInput component, it includes an inputEl property that references the input element inside the component. We can now call focus() on it.

<!-- App.vue -->

<script setup>
import { ref, onMounted } from 'vue'
import BaseInput from './components/BaseInput.vue';

const baseInputEl = ref()

onMounted(() => {
  baseInputEl.value.inputEl.focus() // works
})
</script>

<template>
  <BaseInput ref="baseInputEl" />
</template>
Enter fullscreen mode Exit fullscreen mode

Additionally, in Vue 3.5, we can use the useTemplateRef function to make it easier to access elements in the template without needing to create a reactive variable with the same name as the ref attribute.

<!-- App.vue -->
<script setup>
import { onMounted, useTemplateRef } from 'vue'
import BaseInput from './components/BaseInput.vue';

const baseInputEl = useTemplateRef('base-input')

onMounted(() => {
  baseInputEl.value.inputEl.focus() // works
})
</script>

<template>
  <BaseInput ref="base-input" />
</template>
Enter fullscreen mode Exit fullscreen mode

Top comments (2)

Collapse
 
anirbmuk profile image
Anirban Mukherjee

Nice, didn't know about defineExpose.

Collapse
 
ibrahimalanshor profile image
Ibrahim

Yeah, it’s really useful in Vue 3.