Skip to content

Point to an element in the DOM with useRefs Helper ​

The useRefs helper creates typed, lazy references to elements within your component’s template using a standard CSS selector.
It’s a convenient alternative to manually calling getElement() for each element.

Instead of writing multiple getters, useRefs lets you define all your element references in one place, using a simple mapping function.

useRefs() uses getElement() behind the hood, providing an >>> operator that gets elements through a child's shadow DOM.

Signature ​

typescript
this.useRefs<ElementMap>(
  (ref: <Element extends HTMLElement = HTMLElement, Tag extends keyof HTMLElementTagNameMap | string = string>(
    query: Tag
  ) => SelectorToElementWithFallback<Tag, Element>) => ElementMap
): Readonly<ElementMap>

ref() supports both tag-name inference and an explicit element type:

typescript
const refs = this.useRefs((ref) => ({
  input: ref<HTMLInputElement>('input'),
  button: ref('button'), // inferred as HTMLButtonElement
}));

Parameters ​

  • mapFn: callback function that receives a special ref() function.
    You call ref(selector) for each element you want to reference, and useRefs returns an object with lazy getters for those elements.

Each getter calls getElement() every time it is read: nothing is cached, and a selector that matches nothing throws. It enters a child's shadow root only where the selector says so, with >>>. Refs exist once the template is rendered: reading one in the constructor or a field initializer throws.

Return value ​

  • An object ElementMap where each key corresponds to an element reference, and each property is a getter that returns the corresponding HTMLElement (or subtype).

Example ​

jsx
/// <reference types="@jadis/core/jsx-runtime" />
/** @jsxImportSource @jadis/core */

import { Jadis, createSelector } from '@jadis/core';

class FormComponent extends Jadis {
  static selector = createSelector('form-component');

  templateHtml() {
    return (
      <>
        <input class="my-input" />
        <button>Submit</button>
      </>
    );
  }

  refs = this.useRefs((ref) => ({
    input: ref('input.my-input'),
    button: ref('button'),
  }));

  onConnect() {
    this.refs.button.addEventListener('click', () => {
      console.log('Input value:', this.refs.input.value);
    }, { signal: this.killSignal });
  }
}
tsx
import { Jadis } from '@jadis/core';

class FormComponent extends Jadis {
  static readonly selector = 'form-component';

  templateHtml(): Node {
    return (
      <>
        <input class="my-input" />
        <button>Submit</button>
      </>
    );
  }

  readonly refs = this.useRefs((ref) => ({
    input: ref<HTMLInputElement>('input.my-input'),
    button: ref('button'),
  }));

  onConnect() {
    this.refs.button.addEventListener('click', () => {
      console.log('Input value:', this.refs.input.value);
    }, { signal: this.killSignal });
  }
}
jsx
// @ts-check
/// <reference types="@jadis/core/jsx-runtime" />
/** @jsxImportSource @jadis/core */

import { Jadis, createSelector } from '@jadis/core';

class FormComponent extends Jadis {
  static selector = createSelector('form-component');

  templateHtml() {
    return (
      <>
        <input class="my-input" />
        <button>Submit</button>
      </>
    );
  }

  refs = this.useRefs((ref) => ({
    /** @type {HTMLInputElement} */
    input: ref('input.my-input'),
    button: ref('button'),
  }));

  onConnect() {
    this.refs.button.addEventListener('click', () => {
      console.log('Input value:', this.refs.input.value);
    }, { signal: this.killSignal });
  }
}

Advanced Example: Nested Components ​

You can also traverse into a child component’s shadow DOM using the >>> operator (same as getElement()).

javascript
this.useRefs((ref) => ({
  childButton: ref('child-component >>> button'),
}));

This retrieves the <button> inside the child-component’s shadow root.

TIP

Check out the related helper getElement() used internally by useRefs to perform element lookups.