Skip to content
Meeko
Type to search the guides and the API reference. Open it from any page with / or Ctrl K; move with the arrow keys and open a result with Enter.
Get started

Contents

On this page

ref:nombre

Names a template element or component so the script can read it with useElementRef, typed from its tag or defineExpose.

syntax Since 1.0.0 Source code

ref:nombre, without a value, names a template element or component. The script reads it with useElementRef("nombre"), whose type comes from the tag: HTMLInputElement for an <input>, SVGSVGElement for an <svg> and, for a component, its defineExpose value.

Use it for what the template cannot express: focusing a field, measuring an element, scrolling to it or calling a method exposed by a child component.

Usage#

meeko
<!-- app/components/SearchPanel.meeko -->
<script lang="ts">
const input = useElementRef("input");

onMounted(() => {
  input.value?.focus();
});
</script>

<template>
  <input ref:input type="search" aria-label="Search">
</template>

Type#

meeko
<h2 ref:title>Buscar</h2>

Attributes#

Attribute Type Default Description
ref:<nombre> no value none Names the tag. <nombre> is an identifier, unique in the template.

Valid on HTML and SVG elements, component tags and <component is>. Not valid on <template> or inside <snippet> content (or loose content inside a component tag, which is the default snippet).

Result#

Nothing in HTML. In the script, useElementRef("nombre") returns:

Location of ref: Without await With await
An element ReadonlySignal<Elemento | null>: null in SSR, before hydration and while hidden by if:when The element, never null; the rest of setup continues only in the browser
A component ReadonlySignal<Expuesto | null>, with its defineExpose value The exposed value
Inside each:of ReadonlySignal<readonly Elemento[]>, in document order Does not support await (MEEK056)

Examples#

Call a child component#

The child publishes what the parent can use with defineExpose; the parent names it with ref::

meeko
<!-- app/components/SearchBox.meeko -->
<script lang="ts">
const query = signal("");
function clear(): void {
  query.value = "";
}
defineExpose({ query, clear });
</script>

<template><input type="search" model="query" aria-label="Search"></template>
meeko
<!-- app/components/Toolbar.meeko -->
<script lang="ts">
const box = useElementRef("box");
function reset(): void {
  box.value?.clear();
}
</script>

<template>
  <SearchBox ref:box />
  <button type="button" on:click="reset">Clear</button>
</template>

List rows#

A single ref: inside each:of names all rows:

meeko
<script lang="ts">
const items = signal(["Tea", "Coffee", "Water"]);
const rows = useElementRef("row");
function focusLast(): void {
  rows.value.at(-1)?.focus();
}
</script>

<template>
  <ul>
    <li each:of="items.value" each:as="item" ref:row tabindex="-1">{item}</li>
  </ul>
  <button type="button" on:click="focusLast">Go to last</button>
</template>

An element mounted later#

With await, setup waits until the element exists, including under an if:when that is still false. What follows only runs in the browser:

meeko
<script lang="ts">
const width = signal(0);
const chart = await useElementRef("chart");
const observer = new ResizeObserver(([entry]) => {
  width.value = entry?.contentRect.width ?? 0;
});
observer.observe(chart);
onCleanup(() => observer.disconnect());
</script>

<template><div ref:chart class="chart"></div></template>

The template cannot read observer, declared after await, but it can read width, declared before it.

Common mistakes#

Give it a value#

Incorrectmeeko
<h2 ref:title="heading">Search</h2>

MEEK052: ref:title no lleva valor; escribe ref:title.

Correctmeeko
<h2 ref:title>Search</h2>

Write ref="x" as in Vue#

ref="x" is a literal HTML attribute, not the directive.

Incorrecthtml
<h2 ref="title">Search</h2>

With useElementRef("title") in the script, meeko check reports MEEK056: La plantilla no tiene ref:title; añade ref:title a un elemento o a un componente. On a component, ref="x" produces MEEK032.

Correctmeeko
<h2 ref:title>Search</h2>

The same name in two places#

Incorrectmeeko
<h2 ref:title>Search</h2>
<p ref:title>Results</p>

MEEK053: ref:title ya se usa en la línea 1; una ref nombra un solo lugar de la plantilla (las filas de each:of la comparten). Two ref: directives on the same element produce MEEK052: Un elemento o componente admite una sola directiva ref:.

Correctmeeko
<h2 ref:title>Search</h2>
<p ref:results>Results</p>

A ref: inside a component's content#

A component tag's content is a snippet, which the child can render multiple times.

Incorrectmeeko
<AppDialog><p ref:body>Text</p></AppDialog>

MEEK052: ref: no se admite dentro del contenido de <snippet>, que el hijo puede renderizar cualquier número de veces.

Correctmeeko
<AppDialog ref:dialog><p>Text</p></AppDialog>

Put ref: on the component and let it expose what you need, or on an element outside it.

A name that is not an identifier#

Incorrectmeeko
<h2 ref:main-title>Search</h2>

MEEK052: Nombre de ref no válido: "main-title"; usa un identificador, como ref:input.

Correctmeeko
<h2 ref:mainTitle>Search</h2>

Notes#

  • SSR. A ref: does not exist on the server: the signal is null in SSR and at the start of hydration. When onMounted runs, each visible ref: already has its value.
  • Types. The type comes from the template, not an annotation: an <input> gives HTMLInputElement, without casts. For <component is> with tags, it is the union of their elements; for a generic component, the exposed value with the T inferred by the tag.
  • Hydration. Do not use ref: to write to the DOM before mounting: changes outside Meeko are not preserved if the region is recreated (if:when, each:of).
  • Accessibility. When moving focus with ref:, do so in response to a user action; focusing a field on page load disorients screen reader users.
  • Other forms. bind:ref on a component passes a prop named ref; on an element, a ref attribute.

Was this page helpful?

Add a comment

It is sent when you choose “Yes” or “No”. Only the page, your answer and the comment are stored: no cookies and no personal data.

0 of 2000 characters

Edit on GitHub: docs/en/reference/syntax/ref.md