defineComponent

Define a reusable template with a context factory, props, and slots.

defineComponentApp and Components

Define a reusable template with a context factory, props, and slots.

Overview

The defineComponent function is used to define a Regor component, which encapsulates a part of your user interface (UI) with its own behavior and template. Components allow you to build complex UIs by composing smaller, reusable units.

Try it live

Props and slots in a reusable viewLive API
CHILD COMPONENT / LIVE PROPS

Ada Lovelace

Engineer

PARENT SLOTOpen to collaboration
import {
  computed,
  defineComponent,
  html,
  ref,
  unref,
  type RefOrValue,
} from 'regor'

interface ProfileProps {
  name: RefOrValue<string>
  role: RefOrValue<string>
  compact: RefOrValue<boolean>
}

export function createProfile(interactive = false) {
  const ProfileCard = defineComponent<
    ProfileProps & { initials: RefOrValue<string> }
  >(
    html` <article class="guide-profile" :class="{ 'is-compact': compact }">
      <div class="guide-avatar" aria-hidden="true">{{ initials }}</div>
      <div>
        <h3>{{ name || 'Your name' }}</h3>
        <p>{{ role }}</p>
      </div>
      <footer><slot name="footer"></slot></footer>
    </article>`,
    {
      props: ['name', 'role', 'compact'],
      context: (head) => {
        head.enableSwitch = true // The named slot reads the parent's context.
        return {
          ...head.props,
          initials: computed(
            () =>
              unref(head.props.name)
                .trim()
                .split(/\s+/)
                .slice(0, 2)
                .map((word) => word[0] ?? '')
                .join('')
                .toUpperCase() || '?',
          ),
        }
      },
    },
  )
  return {
    interactive,
    name: ref('Ada Lovelace'),
    role: ref('Engineer'),
    compact: ref(false),
    available: ref(true),
    components: { ProfileCard },
  }
}

export const profileTemplate = html` <div class="guide-demo guide-demo--split">
  <div class="guide-controls">
    <label for="profile-name">Display name</label
    ><input
      id="profile-name"
      type="text"
      maxlength="40"
      r-model="name"
      :disabled="!interactive"
    />
    <label for="profile-role">Role</label
    ><select id="profile-role" r-model="role" :disabled="!interactive">
      <option>Engineer</option>
      <option>Designer</option>
      <option>Researcher</option>
    </select>
    <label class="guide-check"
      ><input type="checkbox" r-model="compact" :disabled="!interactive" />
      Compact layout</label
    >
    <label class="guide-check"
      ><input type="checkbox" r-model="available" :disabled="!interactive" />
      Available for a project</label
    >
  </div>
  <div class="guide-profile-preview">
    <span class="guide-kicker">CHILD COMPONENT / LIVE PROPS</span>
    <ProfileCard :name="name" :role="role" :compact="compact">
      <template #footer
        ><span class="guide-slot-label">PARENT SLOT</span
        ><span
          >{{ available ? 'Open to collaboration' : 'Focused on a project'
          }}</span
        ></template
      >
    </ProfileCard>
  </div>
</div>`
import { createApp, RegorConfig, useScope } from 'regor'
import { apiExamples } from './examples'

const element = document.getElementById('api-demo')
const name = element?.dataset.example
if (element && name && Object.hasOwn(apiExamples, name)) {
  const example = apiExamples[name as keyof typeof apiExamples]
  const scope = useScope<object>(() => example.create(true))
  const config =
    'config' in scope.context && scope.context.config instanceof RegorConfig
      ? scope.context.config
      : undefined
  createApp(scope, { element, template: example.template }, config)
}

The parent controls the form; the child receives props and a named slot.

Usage

Defining a Regor Component

To define a Regor component, call the defineComponent function with the following parameters:

  • template (required): An HTML string or an object specifying the template for rendering the component. It can include the following properties:

    • selector (string, optional): A CSS selector string for the root element of the component. Regor will attempt to find this element in the DOM.
    • element (Element, optional): A reference to the root DOM element of the component. If provided, this element will be used as the component's template.
    • template (string, optional): An HTML string representing the initial content of the component's root element.
    • json (object, optional): A JSON object representing the initial structure of the component's UI.
    • isSVG (boolean, optional): Indicates whether the template contains SVG elements.
  • options (optional): An array of strings that defines component properties or an object that allows you to configure various options for the component, such as whether to use interpolation, props, the component's default name, or the component context.

    • context (optional): A function that defines the Regor context for the component. This function receives a ComponentHead object, which you can use to specify the component's behavior and props. It should return the Regor context.
      • head.autoProps: Automatically merges head.props into the returned component context. Defaults to true.
      • head.entangle: Keeps refs defined in the component context entangled with head.props refs. Defaults to true.
      • head.enableSwitch: Enables slot context switching to the parent. Defaults to false.
      • head.onAutoPropsAssigned: Callback invoked after auto props get assigned to the component context.
      • head.findContext(ContextClass, occurrence?): Finds a parent context instance by instanceof from the captured context stack and returns undefined when missing.
      • head.requireContext(ContextClass, occurrence?): Resolves a parent context instance by instanceof from the captured context stack and throws if the selected occurrence is missing.
      • head.validateProps(schema): Validates selected incoming props at runtime.
      • head.unmount(): Unmounts this component range and runs unmounted handlers for captured contexts.

Example

import { defineComponent, createApp, html } from 'regor'

// Define a Regor component
const myComponent = defineComponent(
  html`<div></div>`, // Define the component content from html string
  {
    context: (head) => ({
      // Define the component's context and behavior here
      // ... other context properties
    }),
  },
)

// Use the created component in your application
createApp({
  components: { myComponent },
})

Parameters

  • template (required): An HTML string or an object specifying the template for rendering the component. It defines the component's UI structure, either by selecting an existing DOM element or providing HTML content or a JSON structure.

  • options (optional): An array of strings that defines component properties or an object that configures various options for the component, including whether to use interpolation, props, the component's default name, or the component context.

Runtime prop validation

Inside context(head), you can validate incoming props explicitly:

import { defineComponent, html, pval } from 'regor'

type Card = {
  title: string
  count?: number
  summary?: string
}

const Card = defineComponent<Card>(html`<article>{{ summary }}</article>`, {
  props: ['title', 'count'],
  context: (head) => {
    head.validateProps({
      title: pval.isString,
      count: pval.optional(pval.isNumber),
    })

    return {
      ...head.props,
      summary: `${head.props.title}:${head.props.count ?? 'none'}`,
    }
  },
})

Behavior:

  • validates only the listed keys
  • follows config.propValidationMode
  • does not mutate head.props
  • does not coerce values

Dynamic bindings and refs

Dynamic single-prop bindings such as :title="titleRef" arrive as refs. Validate them with pval.refOf(...):

type Card = {
  title: Ref<string>
  summary?: string
}

const Card = defineComponent<Card>(html`<article>{{ summary }}</article>`, {
  props: ['title'],
  context: (head) => {
    head.validateProps({
      title: pval.refOf(pval.isString),
    })

    return {
      ...head.props,
      summary: head.props.title(),
    }
  },
})

For object-style :context="{ ... }" values, validate the object shape directly with pval.shape(...).

Validation mode

head.validateProps(...) follows the active RegorConfig.propValidationMode:

  • 'throw' (default): throw on invalid prop
  • 'warn': warn and continue
  • 'off': disable runtime validation

Set it on the config passed to createApp(...).

Return Value

The defineComponent function returns a component object with the following properties:

  • context: The Regor context associated with the component. It defines the component's behavior, data, and reactivity.

  • template: The template (root element) used for rendering the component's UI.

  • inheritAttrs: A boolean indicating whether the component should inherit attributes from its parent. By default, it's set to true.

  • props: An optional object specifying the component's props, if any. This allows you to define input properties for your component.

  • defaultName: An optional default name for the component. This name can be used for debugging and identification purposes.

Create state per instance

Put component state inside its context factory. Separate instances then have separate state and cleanup.

Notes

  • Components are a fundamental building block in Regor applications. They encapsulate UI elements, logic, and reactivity, making it easier to manage complex user interfaces.

  • The template parameter specifies how the component's UI is rendered. You can select an existing element in the DOM, provide HTML content, or use a JSON structure to define the component's structure.

  • For table-centric components (caption/section/row/cell/column components), component templates work with Regor's table preprocessing. Table containers (table, caption, colgroup, thead, tbody, tfoot) and caption/section/row/cell/column placement are normalized to valid structure at runtime.

  • Component tags can be used in PascalCase, camelCase, or kebab-case (for example, <MyComponent>, <myComponent>, or <my-component>).

  • The component context is configured through the options.context callback, which defines the behavior and data of your component.

  • Runtime prop validation is opt-in and local to context(head) through head.validateProps(...).

  • head.autoProps = true merges head.props into the returned component context and also keeps omitted declared prop names local by adding undefined only when the component did not already define that field.

  • head.autoProps = false disables that merge. In that mode, omitted names are not added automatically, so normal parent-context lookup can still resolve them.

  • The options parameter allows you to configure various aspects of the component, such as enabling or disabling interpolation, specifying props, setting a default name, or providing the component context.

  • Once a component is created, it can be used as a building block to construct your application's user interface.

See Also

Related APIs and guides Continue with the references connected to defineComponent.

Back to the API list