For the complete documentation index, see llms.txt. This page is also available as Markdown.

JavaScript Templates

Using JavaScript files in the templates directory with template directives

JavaScript files placed in the templates/ directory are processed through the Elements template engine, allowing you to inject component properties, conditionals, and dynamic values directly into your JavaScript code. This enables you to create interactive components with configuration driven by user properties.

Overview

JavaScript template files provide:

  • Property insertion - Use component properties in JavaScript code

  • Conditional code - Include or exclude JavaScript based on conditions

  • Per-instance configuration - Each component instance gets its own configuration

  • Portal injection - Place scripts in specific page locations using @portal (from an HTML template)

How the core components ship JavaScript: every core component keeps its script inside an HTML template — conventionally templates/alpine.html — wrapped in @portal(bodyEnd, includeOnce: true) (usually with a reverse-DNS id) so the script lands at the end of <body> exactly once, no matter how many instances are on the page. Bare .js template files are also supported (they're processed and inserted inline within <script> tags), but an .html template is the right home for anything that needs the <script> tag or portal markup itself.

File Location

com.yourcompany.component/
├── templates/
│   ├── index.html
│   ├── alpine.html       # Portal-wrapped <script> (core convention)
│   ├── script.js         # Bare JavaScript template (also supported)
│   └── include/
│       └── ...

Basic Usage

JavaScript files can use standard JavaScript syntax along with Elements template directives:

Property Insertion

Insert component properties directly into JavaScript values:

Portal Injection

A common pattern is to use @portal to inject JavaScript into specific page locations, typically bodyEnd. Because the block contains <script> markup, it belongs in an .html template file (such as templates/alpine.html), not a .js file:

Then in your HTML template:

See the @portal documentation for more details.

Examples from Core Components

Accordion Component (Alpine.js)

The Accordion's templates/alpine.html uses a portal to define the Alpine.js component logic once:

Each accordion instance then uses this component with its own properties:

The Gallery registers its lightbox as an Alpine.js factory in a root-level template, templates/alpine-gallery-lightbox.html:

The lightbox markup in templates/include/lightbox.html then binds each instance to the factory:

Note the portal target can be written quoted (@portal("bodyEnd", ...)) or bare (@portal(bodyEnd, ...)) — both forms appear in the core components.

Conditional JavaScript

Use @if directives to conditionally include code. Template @if accepts a single condition only — boolean properties like enableLogging work directly, but comparisons must be computed in hooks.js first. See Combining Conditions.

Processing Behavior

Per-Instance Processing

JavaScript template files are processed once per component instance. Each instance gets its own <script> tag with processed code:

Inline Scripts

Processed JavaScript is inserted inline into the page within <script> tags, not as external files.

Templates vs Assets

Choose the right location for your JavaScript:

Use templates/ JavaScript When:

  • Code needs component property values

  • Code is instance-specific

  • Code needs conditional logic

  • Configuration varies per instance

Example:

Use assets/ JavaScript When:

  • Code is static library code

  • Code is shared across all instances

  • Code is a large framework (Alpine.js, GSAP, etc.)

  • You want better caching and performance

Example:

Combining Both

A common pattern is to define classes in assets/ and instantiate them in templates/:

Best Practices

Use includeOnce for Libraries

When defining reusable functions or classes, use includeOnce:

Avoid Inline Event Handlers

Instead of inline handlers in HTML:

Use proper event listeners in JavaScript:

Escape String Values

Be careful with user-provided strings that might contain quotes:

In hooks.js:

Minimize Template JavaScript

Keep template JavaScript minimal and focused on configuration:

Use Proper Scope

Avoid polluting global scope:

Handle Timing

Ensure DOM is ready before accessing elements:

Common Patterns

Alpine.js Integration

Define Alpine components with property-based configuration:

Registering inside alpine:init is required for browser/publish parity. In the edit canvas Alpine may already be initialised when the script runs, so a bare Alpine.data(...) call can appear to work — but in a browser the factory must exist before Alpine parses x-data attributes, which means it must be registered before alpine:init fires. Always use this pattern.

The Quote-Swap Pattern

The Content Slider builds its Swiper config in hooks.js and swaps the JSON's double-quotes for single-quotes so the value survives inside the double-quoted x-data attribute:

This works because Alpine evaluates x-data as a JavaScript expression, and the single-quoted output ({'loop': true, ...}) is a valid object literal. The Table component defensively handles a string arriving instead, converting the quotes back before parsing:

The caveat: the quote-swap corrupts data that itself contains quote characters, so reserve it for config objects whose values you control. For user-entered content, use a data-* attribute instead.

GSAP Animations

Configure GSAP animations with user properties:

Data Attributes

Set data attributes for JavaScript access:

Passing structured data (objects/arrays) from hooks.js

For structured data, serialise it in hooks.js and embed it in a single-quoted data-* attribute. A single-quoted attribute keeps JSON's double-quotes intact; putting them inside a double-quoted x-data attribute breaks the HTML parse.

Because {{ }} inserts values verbatim (see Escape String Values), entity-encode ', &, and < in hooks.js if the data may contain those characters.

Limitations

No ES Modules

Template JavaScript doesn't support ES module syntax:

Limited Preprocessing

Template JavaScript files don't support TypeScript, Babel, or other preprocessors. Use the Elements template language for logic.

Execution Context

Template JavaScript runs in the page context, not in a controlled environment. Ensure code is safe and handles errors appropriately.

Last updated

Was this helpful?