HTML Attributes Reference

Every data attribute WildflowerJS reads, with its syntax, an example and the builds that include it.

Prefix support: every attribute on this page also works with a wf- prefix: data-wf-bind, data-wf-event-key-enter, data-wf-model-number and so on. When an element carries both forms, the data-wf-* one wins. To stop WildflowerJS reading the plain data-* forms at all, for example beside another library that uses data-action, turn on exclusive mode with data-wf-prefix="true" on the script tag or wildflower.setWfPrefixMode(true). Markers the framework writes for itself, such as data-component-id, keep their plain names in both modes.
At a glance

Builds: all means every build, nano included. Lists ship in mini, lite and above; pools in mini-pool, lite and above; portals, transitions and plugins in standard, spa and full; the router in spa and full; queries and SSR in full.

AttributePurposeBuilds
Components and binding
data-componentMarks a component rootall
data-bindText content from stateall
data-bind-htmlinnerHTML from stateall
data-bind-classClasses from an expressionall
data-bind-styleInline styles from an expressionall
data-bind-attrAttributes from an object expressionall
data-cloakHides content until the first renderall
Conditionals
data-showShows or hides with CSSall
data-renderAdds or removes from the DOMall
data-transitionCSS enter and leave classesstandard, spa, full
Events
data-actionCalls component methods on eventsall
data-event-*Event modifiers: prevent, stop, once, passive, capture, self, outside, debounce, throttle, delay, ifall
data-event-key-*Keyboard filters and combinationsall
Forms
data-modelTwo-way form bindingall
data-model-trim / -number / -lazy / -eventValue and event modifiers for data-modelall
data-validate-on, data-validate, data-validate-message, data-error-forForm validation and error messagesall
Lists and pools
data-listRenders an array through a templatemini, lite and above
data-keyRow identity for lists and poolslist and pool builds
data-template-key + data-typeA template per item typemini, lite and above
data-poolExplicit-control collection renderermini-pool, lite and above
data-pool-fps / -static / -cull / -cull-props / -sortPool rendering optionsmini-pool, lite and above
Composition
data-prop-*Passes one prop to a child componentall
data-propsPasses several props at onceall
data-slot / data-slot-containerProjects content into named slotsall
data-use-template / data-item-template / data-withNamed templates supplied by an ancestorall
data-template-fallbackFallback for a template name that is not foundall
data-portalMoves content elsewhere in the documentstandard, spa, full
data-externalSurvives HTML content updatesall
State and errors
data-storage-key / data-auto-savePersists component state to localStorageall
data-error-fallbackFallback content when a component errorsall
Data, routing and SSR
data-query, data-expectRenders a query; dev-only shape checkfull
data-ssr, data-seed, data-typeServer-rendered components and adopted valuesfull
data-no-routerA link the SPA router leaves alonespa, full
Extending and configuring
data-{name}Custom directives registered with wildflower.directive()all
data-debug, data-error-handling, data-auto-init, data-wf-prefix, data-csp-safeConfiguration on the framework's script tagall

data-component

Marks an element as a component root and associates it with a component definition.

Syntax

<div data-component="component-name">...</div>

Description

When the framework initializes, it scans for elements with data-component and creates component instances. The attribute value must match a registered component name.

Example

<!-- HTML -->
<div data-component="counter">
    <span data-bind="count">0</span>
    <button data-action="increment">+</button>
</div>
// JavaScript - must be registered before or after the element exists
wildflower.component('counter', {
    state: { count: 0 },
    increment() { this.count++; }
});

Notes

  • Each element gets a unique data-component-id automatically assigned
  • Components can be nested - child components initialize after parents
  • The component name should use kebab-case (e.g., user-profile)

data-bind

Binds an element's text content to a state property or computed value.

Syntax

<span data-bind="propertyPath"></span>
<span data-bind="nested.property.path"></span>
<span data-bind="$entityName.path"></span>

Supported Formats

FormatDescriptionExample
property Bind to state or computed property data-bind="username"
nested.path Bind to nested property data-bind="user.address.city"
$entity.path Bind to external entity (store, component, plugin) data-bind="$user.name"

Example

wildflower.component('profile', {
    state: {
        user: { name: 'Alice', role: 'Admin' }
    },
    computed: {
        displayName() {
            return `${this.user.name} (${this.user.role})`;
        }
    }
});
<div data-component="profile">
    <p>Name: <span data-bind="user.name"></span></p>
    <p>Display: <span data-bind="displayName"></span></p>
</div>

In List Context

Inside a data-list, bindings resolve against the current item:

<ul data-list="users">
    <template>
        <li>
            <span data-bind="name"></span> - <span data-bind="email"></span>
            <span data-bind="_index"></span> <!-- Built-in index -->
        </li>
    </template>
</ul>

data-bind-html

Binds an element's innerHTML to a state property. Use with caution.

Syntax

<div data-bind-html="htmlContent"></div>
Security Warning: Never use with untrusted user input. This can lead to XSS vulnerabilities. Only use with content you control.

Example

wildflower.component('content', {
    state: {
        markup: '<strong>Bold</strong> and <em>italic</em>'
    }
});
<div data-component="content">
    <div data-bind-html="markup"></div>
</div>

data-bind-class

Dynamically sets CSS classes based on an expression.

Syntax

<div data-bind-class="expression"></div>

Expression Forms

The expression can produce a string of space-separated class names, an object whose keys are class names and whose values decide whether each class is on, or an array of class names. Classes already written in the element's class attribute are kept; the binding only adds and removes the classes it set itself.

<!-- String: ternary expression -->
<div data-bind-class="isActive ? 'active' : 'inactive'"></div>

<!-- String: multiple classes -->
<div data-bind-class="isError ? 'alert alert-danger' : 'alert alert-success'"></div>

<!-- Object: each class on when its value is truthy -->
<div class="card" data-bind-class="{ 'is-active': isActive, 'is-disabled': !enabled }"></div>

Available Variables

  • State properties: isActive, status, user.role
  • Computed properties, by name: isValid (or computed:isValid)
  • In lists: item properties like done, type, plus _index, _first, _last

Example

wildflower.component('task', {
    state: {
        tasks: [
            { text: 'Learn WildflowerJS', done: true },
            { text: 'Build something', done: false }
        ]
    }
});
<ul data-list="tasks">
    <template>
        <li data-bind-class="done ? 'completed text-muted' : ''">
            <span data-bind="text"></span>
        </li>
    </template>
</ul>

data-bind-style

Dynamically sets inline styles based on an expression.

Syntax

<div data-bind-style="expression"></div>

Expression Format

The expression should evaluate to an object with camelCase CSS properties:

<!-- Object literal -->
<div data-bind-style="{ color: textColor, backgroundColor: bgColor }"></div>

<!-- Computed property returning object -->
<div data-bind-style="dynamicStyles"></div>

<!-- With state reference -->
<div data-bind-style="{ width: progress + '%' }"></div>

Example

wildflower.component('progress-bar', {
    state: {
        progress: 65,
        color: '#4CAF50'
    },
    computed: {
        barStyles() {
            return {
                width: this.progress + '%',
                backgroundColor: this.color,
                height: '20px',
                transition: 'width 0.3s ease'
            };
        }
    }
});
<div data-component="progress-bar">
    <div class="progress-track">
        <div data-bind-style="barStyles"></div>
    </div>
    <span data-bind="progress"></span>%
</div>

data-bind-attr

Dynamically sets HTML attributes based on an object expression.

Syntax

<element data-bind-attr="expression">

Description

The expression should evaluate to an object where keys are attribute names and values are attribute values. A value of null or undefined removes the attribute. On boolean HTML attributes such as disabled, checked or hidden, false removes the attribute and true sets it with an empty value. On any other attribute, true and false are written as the strings "true" and "false", which is what aria-* attributes expect. Event-handler attributes such as onclick are never set.

Example

<img data-bind-attr="{ src: avatarUrl, alt: userName, title: userName }">

<!-- Conditional boolean attribute -->
<button data-bind-attr="{ disabled: isSubmitting }">Submit</button>

<!-- In a pool template -->
<div data-pool="items">
    <template>
        <a data-bind-attr="{ href: url, target: external ? '_blank' : null }"
           data-bind="label"></a>
    </template>
</div>

data-cloak

Prevents flash of unstyled content (FOUC) during initial render.

Syntax

<div data-component="app" data-cloak>...</div>

Description

Add a CSS rule to hide cloaked elements before the framework initializes. After the first render pass completes (including data-show/data-render evaluation), the framework removes the attribute, making the content visible. This is deferred via requestAnimationFrame so conditionals are evaluated before the cloak is lifted.

Required CSS

[data-cloak] { display: none !important; }

The !important is load-bearing. [data-cloak] has the same specificity as a single class, so any component rule that sets display would win the tie and the element would flash until the framework hides it. With the prefix, the rule is [data-wf-cloak] { display: none !important; }.

Example

<style>[data-cloak] { display: none !important; }</style>

<div data-component="dashboard" data-cloak>
    <div data-show="isLoggedIn">Welcome back!</div>
    <div data-show="!isLoggedIn">Please log in.</div>
</div>

data-show

Conditionally shows/hides an element using CSS display property.

Syntax

<div data-show="condition">...</div>
<div data-show="!condition">...</div> <!-- Negated -->

Description

When the condition is falsy, the element gets display: none. The element remains in the DOM.

Example

wildflower.component('loader', {
    state: {
        isLoading: true,
        hasError: false,
        data: null
    }
});
<div data-component="loader">
    <div data-show="isLoading">Loading...</div>
    <div data-show="hasError">Error occurred!</div>
    <div data-show="!isLoading && !hasError">
        <span data-bind="data"></span>
    </div>
</div>

Computed Conditions

<div data-show="shouldShow">...</div>

data-render

Conditionally adds/removes an element from the DOM entirely.

Syntax

<div data-render="condition">...</div>

Difference from data-show

AttributeWhen FalseUse Case
data-show Hidden via CSS (display: none) Frequent toggling, preserve state
data-render Removed from DOM entirely Heavy content, conditional components

Example

<div data-component="app">
    <!-- Component only initialized when isLoggedIn is true -->
    <div data-render="isLoggedIn">
        <div data-component="user-dashboard">...</div>
    </div>

    <div data-render="!isLoggedIn">
        <div data-component="login-form">...</div>
    </div>
</div>

data-transition

Applies CSS transitions when an element with data-show or data-render enters or leaves. Standard, spa and full builds.

Syntax

<div data-show="condition" data-transition="transition-name">...</div>

CSS Classes Applied

ClassWhen Applied
{name}-enterStarting state for enter
{name}-enter-activeActive/ending state for enter
{name}-leaveStarting state for leave
{name}-leave-activeActive/ending state for leave

The classes come off when the element's CSS transition ends. With no transition duration in the CSS they come off at once, so the CSS is what gives the effect its length.

Example CSS

.fade-enter {
    opacity: 0;
}
.fade-enter-active {
    opacity: 1;
    transition: opacity 300ms ease-in;
}
.fade-leave {
    opacity: 1;
}
.fade-leave-active {
    opacity: 0;
    transition: opacity 300ms ease-out;
}

Example HTML

<div data-show="isVisible" data-transition="fade">
    This content fades in and out
</div>

See Transitions for JavaScript hooks.

data-action

Binds DOM events to component methods.

Syntax

<!-- Default click event -->
<button data-action="methodName">Click</button>

<!-- Specific event -->
<input data-action="input:onType">
<form data-action="submit:onSubmit">

<!-- Several actions on one element, separated by spaces -->
<input data-action="focus:onFocus blur:onBlur">

<!-- Arguments -->
<button data-action="setFilter('done')">Done</button>

Method Signature

methodName(event, element, context) {
    // event - The DOM event object
    // element - The element that triggered the event
    // context - Additional context (index in lists, etc.)
}

Example

wildflower.component('search', {
    state: { query: '', results: [] },

    onSearch(event, element) {
        this.fetchResults();
    },

    async fetchResults() {
        // ... fetch logic
    }
});
<form data-component="search" data-action="submit:onSearch" data-event-prevent>
    <input type="text" data-model="query">
    <button type="submit">Search</button>
</form>

data-event-*

Modifiers that sit beside data-action on the same element and change how its events are handled.

AttributeEffect
data-event-preventCalls event.preventDefault() before the handler runs
data-event-stopCalls event.stopPropagation()
data-event-onceThe handler fires at most once, then the listener is removed
data-event-passiveRegisters a passive listener (improves scroll performance)
data-event-captureListens in the capture phase
data-event-selfFires only when the event's target is the element itself, not a child
data-event-outsideFires on clicks outside the element (for closing menus and popovers)
data-event-debounce="300"Waits until events stop for this many milliseconds (default 300)
data-event-throttle="300"Runs at most once per this many milliseconds (default 300). If debounce is also set, debounce wins
data-event-delay="500"Runs the handler after this many milliseconds, unless the component was destroyed in between
data-event-if="expression"Runs the handler only when the expression, evaluated against component state, is truthy

Example

<input data-action="input:search" data-event-debounce="300">
<div class="menu" data-action="closeMenu" data-event-outside>...</div>
<button data-action="save" data-event-if="isDirty">Save</button>

See Advanced Events for more.

data-event-key-*

Keyboard filters: the action runs only for the listed keys. They apply to keyboard events (keydown, keyup).

Syntax

<!-- One key -->
<input data-action="keydown:submit" data-event-key-enter>

<!-- Any of several keys -->
<input data-action="keydown:close" data-event-key-esc data-event-key-tab>

<!-- A combination, joined with + -->
<div data-action="keydown:save" data-event-key-ctrl+s>...</div>

Keys

  • Names match event.key, lowercased: data-event-key-a, data-event-key-f2.
  • Aliases: enter (Enter or Return), esc and escape, space, up, down, left, right, tab, delete and backspace (each matches both).
  • A bare data-event-key-ctrl, -alt, -shift or -meta requires that modifier on every match.
  • When several keys or combinations are listed, any one of them matches.

data-model

Creates two-way binding between a form input and state property.

Syntax

<input data-model="propertyPath">

Supported Elements

ElementEventProperty
<input type="text">inputvalue (string)
<input type="number">, type="range"inputvalue (number; empty stays '')
<input type="checkbox">changechecked (boolean)
<input type="radio">changevalue (string)
<textarea>inputvalue (string)
<select>changevalue (string)

Example

wildflower.component('form-demo', {
    state: {
        username: '',
        email: '',
        subscribe: false,
        plan: 'free'
    }
});
<div data-component="form-demo">
    <input type="text" data-model="username" placeholder="Username">
    <input type="email" data-model="email" placeholder="Email">

    <label>
        <input type="checkbox" data-model="subscribe">
        Subscribe to newsletter
    </label>

    <select data-model="plan">
        <option value="free">Free</option>
        <option value="pro">Pro</option>
    </select>
</div>

data-model-trim / -number / -lazy / -event

Presence attributes that change how data-model writes to state.

AttributeEffect
data-model-trimTrims whitespace from the value before writing it
data-model-numberWrites the value as a number (parseFloat). An empty field stays ''; text that is not a number is kept as typed
data-model-lazyWrites on change and blur instead of on every keystroke
data-model-event="evt"For web components: the event that carries the new value (for example sl-input). The default listens for both input and change

Example

<input data-model="quantity" data-model-number>
<input data-model="name" data-model-trim data-model-lazy>
<sl-input data-model="email" data-model-event="sl-input"></sl-input>

See Forms and Component Libraries.

data-validate-on, data-validate, data-validate-message, data-error-for

Form validation. The form opts in with data-validate-on; each input is checked with the browser's own constraints (required, type="email", minlength and so on) plus an optional data-validate rule.

AttributeOnEffect
data-validate-on="submit"formWhen to validate: a comma list of submit and blur. A failed submit stops the form's data-action from running. A change event always re-validates the changed field
data-validate="rule"inputAn extra rule: number, integer, or a regular expression written as /pattern/
data-validate-message="text"inputThe message for a failed /pattern/ rule
data-error-for="path"any elementShows the error for the input whose data-model is path, and hides when that input is valid

A field that fails gets the class invalid. The component's state gets formValid and validationErrors. Add novalidate to the form so the browser's own popups stay out of the way.

Example

<form data-validate-on="blur,submit" data-action="submit:register" novalidate>
    <input type="email" data-model="email" required>
    <span class="error" data-error-for="email"></span>

    <input data-model="zip" data-validate="/^\d{5}$/" data-validate-message="Five digits">
    <span class="error" data-error-for="zip"></span>

    <button type="submit">Register</button>
</form>

See Forms and Advanced Forms.

data-list

Renders a list of items from an array in state. Mini, lite, standard, spa and full builds.

Syntax

<container data-list="arrayPath">
    <template>
        <!-- Item template -->
    </template>
</container>

<!-- From computed property -->
<container data-list="filteredItems">...</container>

Put data-list on an element inside the component, not on the component's root element.

Template Context Variables

VariableTypeDescription
_indexnumberZero-based index of current item
_lengthnumberTotal number of items
_firstbooleanTrue if first item
_lastbooleanTrue if last item

Example

wildflower.component('todo-list', {
    state: {
        todos: [
            { id: 1, text: 'Learn WildflowerJS', done: true },
            { id: 2, text: 'Build an app', done: false }
        ]
    },

    removeTodo(event, element, context) {
        this.todos.splice(context.index, 1);
    }
});
<div data-component="todo-list">
    <ul data-list="todos" data-key="id">
        <template>
            <li data-bind-class="done ? 'completed' : ''">
                <!-- data-model writes the item's done field; no action needed -->
                <input type="checkbox" data-model="done">
                <span data-bind="text"></span>
                <span class="index">#<span data-bind="_index"></span></span>
                <button data-action="removeTodo">Delete</button>
            </li>
        </template>
    </ul>
</div>

data-key

Specifies a unique identifier property for optimized list rendering.

Syntax

<ul data-list="items" data-key="id">...</ul>

Description

When items have unique IDs, the framework can optimize updates by reusing existing DOM elements. Without keys, items are matched by index which can cause issues when reordering.

Auto-Detection

If items have an id property, the framework automatically uses it for keying. Use data-key to specify a different property.

Example

<!-- Using 'id' property (auto-detected if present) -->
<ul data-list="users" data-key="id">...</ul>

<!-- Using custom key property -->
<ul data-list="products" data-key="sku">...</ul>

data-template-key + data-type

Renders each list item with a template chosen by one of its fields. Mini, lite, standard, spa and full builds.

Syntax

<div data-list="messages" data-key="id" data-template-key="kind">
    <template data-type="text"><p data-bind="body"></p></template>
    <template data-type="image"><img data-bind-attr="{ src: url }"></template>
    <template><p>Unsupported message</p></template>
</div>

Each item uses the <template> whose data-type equals the item's kind. A template with no data-type is the default. See Dynamic Templates.

data-pool

Explicit-control collection renderer. Unlike data-list, pool items are plain JS objects with zero reactive proxy overhead. Handles full CRUD, selection, and bulk operations, faster than the reactive path for performance-sensitive workloads, real-time data, and per-frame animation. DOM updates are batched via a shared requestAnimationFrame loop. Mini-pool, lite, standard, spa and full builds.

Syntax

<div data-pool="poolName" data-key="id">
    <template>
        <!-- Entity template -->
    </template>
</div>

Declaration (preferred)

pools: {
    enemies: {
        onAdd: 'onSpawn',       // lifecycle hook (string ref or inline fn)
        onRemove: 'onDeath',    // fires before individual removal
        onClear: 'onWaveEnd'    // fires once on bulk clear
    },
    projectiles: {}             // no hooks needed
}
// Access: this.pools.enemies.add({...})

API (container this.pools.name, or this.getPool(name) for any pool)

Method / PropertyDescription
pool.add(obj)Add an entity to the pool
pool.remove(key)Remove entity by key value
pool.get(key)Get entity object by key (or undefined)
pool.clear()Remove all entities
pool.itemsRaw array of entity objects, mutate properties freely
pool.sizeCurrent entity count
pool.getElement(key)Get DOM element for an entity by key
pool.markDirty(key)Mark a single entity for re-render. Switches the pool from animation mode (default: all entities flushed every frame) to targeted mode (only dirty entities are flushed). Use for sparse, data-driven updates where most entities are unchanged between frames.

Pool Modifier Attributes

AttributeDescription
data-pool-fps="N"Cap render rate to N frames per second. Omit for native frame rate.
data-pool-staticBoolean (no value): passive pool, skips rAF flush entirely. With a value (data-pool-static="propName"): per-entity static property; entities with a truthy value for that property are excluded from the per-frame flush.
data-pool-cull="N"Enable spatial culling. N is padding in pixels around the viewport; entities outside the padded bounds are skipped during flush.
data-pool-cull-props="x,y"Data-based culling via entity properties. Accepts "x,y" (point) or "x,y,w,h" (rect): maps entity property names to spatial coordinates for culling decisions.
data-pool-sort="prop"Z-index sort by entity property. Use data-pool-sort="prop:desc" for descending order.

Supported Template Bindings

data-bind, data-bind-style, data-bind-attr, data-bind-class, data-show, and data-action (handled by delegation; the handler receives the entity).

Constraints

  • Pool templates can only reference entity properties; component state, computed properties, and store values are NOT available inside pool templates
  • data-key specifies the unique identifier property (defaults to id)
  • Pools are automatically cleaned up when the owning component is destroyed

Example

<div data-pool="enemies" data-key="id">
    <template>
        <div class="sprite" data-bind-style="{ left: x + 'px', top: y + 'px' }">
            <img data-bind-attr="{ src: imgSrc }">
            <span data-bind="label"></span>
        </div>
    </template>
</div>
wildflower.component('game-board', {
    init() {
        this.pools.enemies.add({ id: 1, x: 100, y: 200, imgSrc: 'orc.png', label: 'Orc' });
    },

    gameLoop() {
        // Animation mode (default): mutate freely, all entities flush every frame
        for (const enemy of this.pools.enemies.items) {
            enemy.x += enemy.speed;
        }
    },

    // Targeted mode: call markDirty() for sparse updates (e.g., data dashboards)
    updateScore(id, newScore) {
        const enemy = this.pools.enemies.get(id);
        enemy.score = newScore;
        this.pools.enemies.markDirty(id); // only this entity re-renders
    }
});

When to Use

Start with data-list; it's the right default. Use data-pool when you need explicit update control, better performance at scale, real-time data, or high-frequency rendering. Use data-list when items need two-way binding (data-model), parent computed properties, or nested lists.

data-prop-*

Passes data from parent to child components via props.

Syntax

<!-- Pass state property -->
<div data-component="child" data-prop-user="currentUser"></div>

<!-- Pass a literal string: quote it -->
<div data-component="child" data-prop-theme="'dark'"></div>

<!-- Text that could not be a state name is also passed as written -->
<div data-component="child" data-prop-title="Hello World"></div>

<!-- Numbers, booleans and null are literals -->
<div data-component="child" data-prop-count="42" data-prop-visible="true"></div>

<!-- Pass parent method as callback -->
<div data-component="child" data-prop-on-save="handleSave"></div>

How values resolve

  1. true, false, null, numbers, and anything in single or double quotes are literals.
  2. Otherwise the value is looked up in the parent: a $entity.path, a state path, a computed property, then a parent method (passed bound to the parent).
  3. A value that looks like a name but finds nothing (data-prop-theme="dark" with no dark in the parent) gives undefined, so the prop's default applies and development builds warn. Quote it to pass the word itself.
  4. A value that could not be a name, such as Hello World, is passed as the literal text.

Description

Props provide explicit data flow from parent to child components. The attribute name after data-prop- becomes the prop name in camelCase (e.g., data-prop-user-name becomes userName).

Example

// Child component defines expected props
wildflower.component('user-card', {
    props: {
        user: { type: Object, required: true },
        theme: { type: String, default: 'light' }
    },
    computed: {
        displayName() {
            return this.props.user.name;
        }
    }
});
<div data-component="parent">
    <div data-component="user-card"
         data-prop-user="currentUser"
         data-prop-theme="'dark'">
        <span data-bind="props.user.name"></span>
    </div>
</div>

Notes

  • Props are accessed via this.props in JavaScript and props.* in bindings
  • Props are reactive - child updates when parent data changes
  • See Props Guide for type validation and defaults

data-props

Passes multiple props to a child component in a single attribute using object expression syntax.

Syntax

<!-- Values resolve from parent state -->
<div data-component="child" data-props="{ title: cardTitle, color: accentColor }"></div>

<!-- Quoted string values (commas allowed inside quotes) -->
<div data-component="child" data-props="{ label: 'hello, world', color: color }"></div>

Description

A convenience syntax for passing multiple props at once instead of using separate data-prop-* attributes. Keys become prop names; values are resolved as parent state paths (or as literal strings when quoted).

Example

<!-- These two are equivalent -->
<div data-component="card"
     data-props="{ title: cardTitle, color: accentColor }"></div>

<div data-component="card"
     data-prop-title="cardTitle"
     data-prop-color="accentColor"></div>

Notes

  • Values update reactively when the parent state changes
  • Can be used alongside individual data-prop-* attributes; individual attributes take precedence
  • See Props Guide for full details

data-slot / data-slot-container

Places marked content into named insertion points inside the same component.

Syntax

<div data-component="card">
    <div data-slot-container="slotName"></div>   <!-- where it goes -->
    <div data-slot="slotName">Content</div>       <!-- what goes there -->
</div>

Description

When the component initializes, each data-slot-container in it is emptied and receives the first element in the same component whose data-slot has the same name. Both sit inside the one component element: the containers usually come from the component's markup and the slot content from the page that uses it.

Example

<div data-component="card">
    <div class="card-header" data-slot-container="header"></div>
    <div class="card-body" data-slot-container="body"></div>

    <div data-slot="header"><h3>Card Title</h3></div>
    <div data-slot="body"><p>Card content goes here.</p></div>
</div>

See Slots.

data-use-template

References a named template defined by an ancestor component for rendering.

Syntax

<!-- Child references an ancestor's named template -->
<div data-use-template="templateName" data-with="dataPath"></div>

<!-- Only look in one named ancestor component -->
<div data-use-template="templateName@componentName" data-with="dataPath"></div>

Related Attributes

AttributeDescription
data-item-template="name" An ancestor defines a named template
data-use-template="name" Uses the template; name@component limits the search to that ancestor. Also works as a list's template
data-with="path" Binds the template to a state path (not used inside a data-list, where each row binds to its item)
data-template-fallback="name" A template in the same container used when name is not found

When the name is not found, the framework uses the content written inside the data-use-template element, then a data-template-fallback template with the same name.

Example

<!-- Parent defines how user should be displayed -->
<div data-component="user-page">
    <template data-item-template="userCard">
        <div class="card">
            <h5 data-bind="name"></h5>
            <p data-bind="email"></p>
        </div>
    </template>

    <!-- Child uses the template with its data -->
    <div data-component="profile">
        <div data-use-template="userCard" data-with="user"></div>
    </div>
</div>

Notes

  • Enables inversion of control - parent controls presentation, child provides data
  • Templates are fully reactive to data changes
  • See Configurable Templates Guide for advanced usage

data-item-template

Defines a named template that descendant components can reference.

Syntax

<template data-item-template="templateName">
    <!-- Template content with data-bind attributes -->
</template>

See data-use-template for complete usage.

data-portal

Moves an element's content to another place in the document, such as the end of <body> for modals and tooltips. The content keeps its bindings and actions. Standard, spa and full builds.

Syntax

<!-- The value is a CSS selector for the destination -->
<div data-portal="#modal-root" data-show="isOpen">
    Modal content here
</div>

<!-- Empty, or "body", means document.body -->
<div data-portal>...</div>

Description

  • The element's children move into the first element matching the selector. The element itself stays where it is.
  • With data-show or data-render on the portal element, nothing moves while the condition is false. When it turns false again, data-show brings the content back hidden and data-render removes it.
  • If no element matches the selector, a warning is logged and nothing moves.
  • Portal content is cleaned up with its component.

Example

<div data-component="modal-demo">
    <button data-action="openModal">Open Modal</button>

    <div data-portal="#modal-root" data-show="isModalOpen">
        <div class="modal-backdrop">
            <div class="modal-content">
                <h2>Modal Title</h2>
                <p>Modal body content</p>
                <button data-action="closeModal">Close</button>
            </div>
        </div>
    </div>
</div>

<!-- Typically at the end of body -->
<div id="modal-root"></div>

See Portals.

data-external

Preserves an element and its component during HTML content updates.

Syntax

<div data-external data-component="live-chart">...</div>

Description

When parent content is updated via data-bind-html or programmatic innerHTML changes, elements marked with data-external are preserved rather than destroyed and recreated. This is useful for:

  • Interactive components that maintain internal state (charts, editors)
  • Components with expensive initialization
  • Live code examples in documentation

Example

<div data-component="content-page">
    <!-- This content may be updated dynamically -->
    <div data-bind-html="pageContent">
        <!-- This chart component survives content updates -->
        <div data-external data-component="live-chart">
            <canvas id="myChart"></canvas>
        </div>
    </div>
</div>

Notes

  • The element must have a stable position - use placeholder markers if needed
  • Works with both components and regular elements
  • Garbage collection skips elements marked as external

data-storage-key / data-auto-save

Persists a component's state in localStorage. Both go on the component's root element.

AttributeEffect
data-storage-key="key"Before init(), loads the saved state stored under key over the declared state. Saving is then up to you: this.saveToStorage() (and this.loadFromStorage() to reload)
data-auto-saveWith a storage key, saves the whole state after every change

Example

<div data-component="settings" data-storage-key="app-settings" data-auto-save>
    <input type="checkbox" data-model="darkMode"> Dark mode
</div>

See Data Attributes.

data-error-fallback

What a component shows when it throws an error that no onError handler deals with. Goes on the component's root element.

Syntax

<!-- A selector for an element inside the component -->
<div data-component="widget" data-error-fallback=".error-message">
    <div class="content">...</div>
    <div class="error-message" style="display:none">Something went wrong.</div>
</div>

<!-- Or the id of a <template> anywhere in the document -->
<div data-component="widget" data-error-fallback="#widget-error">...</div>

With a selector, the component's other children are hidden and the matching element is shown. With the #id of a <template>, the component's content is replaced by the template's content, and the original is kept so the component can be reset. See Error Boundaries.

data-query, data-expect

Renders a query declared with wildflower.query(). Full builds.

Syntax

<!-- With a <template> child: one row per result -->
<ul data-query="articles">
    <template><li data-bind="title"></li></template>
</ul>

<!-- Without one: a single record -->
<div data-query="profile"><h2 data-bind="name"></h2></div>

A data-query element must be inside a component. data-expect="id:number, title:string" on the same element makes development builds warn when incoming rows drift from that shape; production builds ignore it. See Data Query and Shapes.

data-ssr, data-seed, data-type

Attributes for server-rendered markup. Full builds.

AttributeEffect
data-ssr="true"On a component root: the server-rendered DOM is adopted as the component's content and state, then made live
data-seed='{"key": value}'JSON with extra state that is not shown in the markup, merged into the adopted state or rows
data-type="number"On a bound element being adopted: reads its text as a number. Also boolean, and json for SSR component state

See Server-Side Rendering and Queries with SSR.

data-no-router

On a link, tells the SPA router not to handle it, so the browser follows it normally. Spa and full builds.

<a href="/downloads/report.pdf" data-no-router>Report</a>

External links, links with a target other than _self, download links, and clicks with a modifier key are already left alone. See Routing.

data-{name}: custom directives

An attribute of your own, registered with wildflower.directive(). Its value is a state path.

wildflower.directive('tooltip', {
    init(el, value, context) { /* context.resolvedValue is the value at the path */ },
    update(el, newValue, oldValue, context) { /* runs when the value changes */ },
    destroy(el, context) { /* clean up */ }
});
<button data-tooltip="helpText">?</button>

Directive names cannot start with wf-: data-wf-tooltip is the prefixed form of tooltip. See Plugins and Directives.

Script-tag attributes

Configuration read from the <script> tag that loads WildflowerJS. These keep their plain names.

AttributeValuesDefault
data-debugPresent or "true": debug on. Any other value: offOn in development builds, off in .min builds
data-error-handlinglog, throw or silentlog
data-auto-init"false" stops the automatic start; anything else leaves it onOn
data-wf-prefix"true" turns on exclusive mode (only data-wf-* attributes are read). A bare attribute does notOff
data-csp-safePresent or "true": always use the CSP-safe expression evaluatorOff (chosen automatically when the page's CSP forbids eval)
<script src="wildflower.min.js" data-wf-prefix="true" data-error-handling="throw"></script>

See Configuration.