Skip to main content

Core Concepts: Managing the DOM

When writing JavaScript for the browser, you usually need to interact with HTML elements on the page. In traditional web development, you might use document.querySelector('.my-class') or document.getElementById('my-id').

In Coralite, direct DOM querying is typically replaced by the built-in refs plugin. This plugin provides a safe, runtime DOM element targeting system specifically designed for component encapsulation. The Coralite refs system generates unique IDs directly assigned to the ref attribute, allowing you to leave the standard id attribute intact for other uses (like linking a label's for attribute to an input's id).

Why Use Refs Instead of querySelector? #

How to Use Refs #

Using the refs plugin is a simple two-step process: defining the reference in your HTML template, and accessing it in your client-side script.

1. Template Setup #

Add a ref="yourName" attribute to any HTML element inside your component's <template>.

During the server-side build, Coralite intercepts this attribute, generates a unique, component-instance-specific ID for the element, and maps it behind the scenes.

HTML
Code copied!
<template id="my-form">
  <form>
    

    <input type="text" ref="usernameInput" placeholder="Enter username"></input>
    

    <button type="submit" ref="submitBtn">Submit</button>
  </form>
</template>

2. Script Usage #

Inside your defineComponent's client.script, the refs plugin provides a helper function: helpers.refs('yourName').

Call this function with the name you defined in the template to retrieve the actual DOM element.

HTML
Code copied!
<script type="module">  
  import { defineComponent } from 'coralite'
  
  export default defineComponent({
    client: {
      script: (context) => {
        // Extract the refs helper from the context
        const { helpers } = context
        const refs = helpers.refs
  
        // Safe DOM element retrieval
        const input = refs('usernameInput')
        const button = refs('submitBtn')
  
        // Now use standard DOM APIs
        button.addEventListener('click', (e) => {
          e.preventDefault()
          console.log(`Submitted username: ${input.value}`)
        })
      }
    }
  })
</script>

Under the Hood: Scoping & Safety #

The refs plugin is highly context-aware. Depending on how your component is compiled, it behaves differently to ensure maximum safety:

  1. Global Fallback: For declarative components, the plugin queries root.querySelector('[ref="..."]') where the generated ref ID is assigned. The root represents the ShadowRoot for web components or the Document for declarative components.
  2. Caching: The first time you call refs('myEl'), it performs the DOM query. If found, the DOM node is cached locally in the plugin. The next time you call refs('myEl'), it returns immediately without querying the DOM again.
  3. Null Safety: If the element isn't found (perhaps conditionally rendered out), the helper safely returns null without throwing an error.

E2E Testing & External Querying #

At build time, Coralite assigns a unique string to the ref attribute using the pattern: <component-id>__<refName>-<index>. For E2E testing frameworks (like Playwright) or external scripts, you should query this compiled ref attribute directly instead of relying on arbitrary CSS classes or standard IDs.

For example, if you defined <button ref="submitBtn"> in a component named my-form, you could locate it in a Playwright test like this:

javascript
Code copied!

await page.locator('[ref="my-form__submitBtn-0"]').click();
    

Start Building with Coralite!

Use the scaffolding script to get jump started into your next project with Coralite

Copied commandline!