Vue cookbook · Beginner
Access child component methods with template refs and defineExpose
A parent needs to focus an input or reset a form inside a child component.
Approach
Expose a small, explicit API from the child with defineExpose, and reference it in the parent with
useTemplateRef, typed with InstanceType<typeof Child>.
Solution
<!-- SearchBox.vue -->
<script setup lang="ts">
import { ref, useTemplateRef } from "vue";
const query = ref("");
const input = useTemplateRef<HTMLInputElement>("input");
defineExpose({
focus: () => input.value?.focus(),
clear: () => (query.value = ""),
});
</script>
<template>
<input ref="input" v-model="query" type="search" />
</template>
<!-- Toolbar.vue -->
<script setup lang="ts">
import { useTemplateRef } from "vue";
import SearchBox from "./SearchBox.vue";
const search = useTemplateRef<InstanceType<typeof SearchBox>>("search");
</script>
<template>
<SearchBox ref="search" />
<button @click="search?.focus()">Search (/)</button>
<button @click="search?.clear()">Clear</button>
</template>
Pitfalls
- Reaching into a child's internal state;
<script setup>components are closed by default for good reason. - Using refs to pass data down that should be props.
- Accessing refs before mount (they're
nulluntil then).
Variations
- For many imperative needs (focus on mount), a
v-focuscustom directive is simpler. - Use the
ComponentExposedtype fromvue-component-type-helpersfor generic components.
Further reading: Template refs
Reference: https://vuejs.org/guide/essentials/template-refs.html
More Vue recipes
- Add SEO metadata and structured data in Nuxt
- Build an accessible modal with Teleport
- Build custom inputs with defineModel and modifiers
- Catch component errors with an error boundary
- Debounce user input with a custom ref
- Fetch data in a composable and cancel stale requests
- Fetch, refresh and share data with Nuxt useFetch
- Implement a dark mode toggle that respects system settings