Attributes

Data attributes have special casing rules, and can be aliased to avoid conflicts with other libraries.

The Datastar VSCode extension and IntelliJ plugin provide autocompletion for all data-* attributes.

data-attr #

Sets the value of any HTML attribute to an expression, and keeps it in sync.

1<div data-attr-title="$foo"></div>

The data-attr attribute can also be used to set the values of multiple attributes on an element using a set of key-value pairs, where the keys represent attribute names and the values represent expressions.

1<div data-attr="{title: $foo, disabled: $bar}"></div>

data-bind #

Creates a signal (if one doesn’t already exist) and sets up two-way data binding between it and an element’s value. This means that the value of the element is updated when the signal changes, and the signal is updated when the value of the element changes.

The data-bind attribute be placed on any HTML element on which data can be input or choices selected from (input, select,textarea elements, and web components). Event listeners are added for change, input and keydown events.

1<input data-bind-foo />

The signal name can be specified in the key (as above), or in the value (as below). This can be useful depending on the templating language you are using.

1<input data-bind="foo" />

The initial value of the signal is set to the value of the element, unless a signal has already been defined. So in the example below, $foo is set to bar.

1<input data-bind-foo value="bar" />

Whereas in the example below, $foo inherits the value baz of the predefined signal.

1<div data-signals-foo="baz">
2    <input data-bind-foo value="bar" />
3</div>

Multiple input values can be assigned to a single signal by predefining the signal as an array. So in the example below, $foo is set to ['bar', 'baz'] when both checkboxes are checked.

1<div data-signals-foo="[]">
2    <input data-bind-foo type="checkbox" value="bar" />
3    <input data-bind-foo type="checkbox" value="baz" />
4</div>

Modifiers

Modifiers allow you to modify behavior when binding signals.

1<input data-bind-my-signal__case.kebab />

data-class #

Adds or removes a class to or from an element based on an expression.

1<div data-class-hidden="$foo"></div>

If the expression evaluates to true, the hidden class is added to the element; otherwise, it is removed.

The data-class attribute can also be used to add or remove multiple classes from an element using a set of key-value pairs, where the keys represent class names and the values represent expressions.

1<div data-class="{hidden: $foo, 'font-bold': $bar}"></div>

Modifiers

Modifiers allow you to modify behavior defining a class name.

1<div data-class-my-class__case.camel="$foo"></div>

data-computed #

Creates a signal that is computed based on an expression. The computed signal is read-only, and its value is automatically updated when any signals in the expression are updated.

1<div data-computed-foo="$bar + $baz"></div>

Computed signals are useful for memoizing expressions containing other signals. Their values can be used in other expressions.

1<div data-computed-foo="$bar + $baz"></div>
2<div data-text="$foo"></div>
Computed signals must not be used for performing actions (changing other signals, actions, JavaScript functions, etc.). If you need to perform an action in response to a signal change, use the data-effect attribute.

Modifiers

Modifiers allow you to modify behavior when defining computed signals.

1<div data-computed-my-signal__case.kebab="$bar + $baz"></div>

data-effect #

Executes an expression on page load and whenever any signals in the expression change. This is useful for performing side effects, such as updating other signals, making requests to the backend, or manipulating the DOM.

1<div data-effect="$foo = $bar + $baz"></div>

data-ignore #

Datastar walks the entire DOM and applies plugins to each element it encounters. It’s possible to tell Datastar to ignore an element and its descendants by placing a data-ignore attribute on it. This can be useful for preventing naming conflicts with third-party libraries, or when you are unable to escape user input.

1<div data-ignore data-show-thirdpartylib="">
2    <div>
3        This element will not be processed by Datastar.
4    </div>
5</div>

Modifiers

data-ignore-morph #

Similar to the data-ignore attribute, the data-ignore-morph attribute tells the PatchElements watcher to skip processing an element and its children when morphing elements.

1<div data-ignore-morph>
2    This element will not be morphed.
3</div>
To remove the data-ignore-morph attribute from an element, simply patch the element with the data-ignore-morph attribute removed.

data-indicator #

Creates a signal and sets its value to true while an SSE request request is in flight, otherwise false. The signal can be used to show a loading indicator.

1<button data-on-click="@get('/endpoint')"
2        data-indicator-fetching
3></button>

This can be useful for show a loading spinner, disabling a button, etc.

1<button data-on-click="@get('/endpoint')"
2        data-indicator-fetching
3        data-attr-disabled="$fetching"
4></button>
5<div data-show="$fetching">Loading...</div>

The signal name can be specified in the key (as above), or in the value (as below). This can be useful depending on the templating language you are using.

1<button data-indicator="fetching"></button>

Modifiers

Modifiers allow you to modify behavior when defining indicator signals.

data-json-signals #

Sets the text content of an element to a reactive JSON stringified version of signals. Useful when troubleshooting an issue.

1<!-- Display all signals -->
2<pre data-json-signals></pre>

You can optionally provide a filter object to include or exclude specific signals using regular expressions.

1<!-- Only show signals that include "user" in their path -->
2<pre data-json-signals="{include: /user/}"></pre>
3
4<!-- Show all signals except those ending with "temp" -->
5<pre data-json-signals="{exclude: /temp$/}"></pre>
6
7<!-- Combine include and exclude filters -->
8<pre data-json-signals="{include: /^app/, exclude: /password/}"></pre>

Modifiers

Modifiers allow you to modify the output format.

1<!-- Display filtered signals in a compact format -->
2<pre data-json-signals__terse="{include: /counter/}"></pre>

data-on #

Attaches an event listener to an element, executing an expression whenever the event is triggered.

1<button data-on-click="$foo = ''">Reset</button>

An evt variable that represents the event object is available in the expression.

1<div data-on-myevent="$foo = evt.detail"></div>

The data-on attribute works with events and custom events. The data-on-submit event listener prevents the default submission behavior of forms.

Events listeners are only triggered when the event is trusted. This behavior can be bypassed using the __trusted modifier.

Modifiers

Modifiers allow you to modify behavior when events are triggered. Some modifiers have tags to further modify the behavior.

* Only works with built-in events.

1<button data-on-click__window__debounce.500ms.leading="$foo = ''"></button>
2<div data-on-my-event__case.camel__trusted="$foo = ''"></div>

data-on-intersect #

Runs an expression when the element intersects with the viewport.

1<div data-on-intersect="$intersected = true"></div>

Modifiers

Modifiers allow you to modify the element intersection behavior and the timing of the event listener.

1<div data-on-intersect__once__full="$fullyIntersected = true"></div>

data-on-interval #

Runs an expression at a regular interval. The interval duration defaults to one second and can be modified using the __duration modifier.

1<div data-on-interval="$count++"></div>

Modifiers

Modifiers allow you to modify the interval duration.

1<div data-on-interval__duration.500ms="$count++"></div>

data-on-load #

Runs an expression when the element is loaded into the DOM.

1<div data-on-load="$count = 1"></div>

Modifiers

Modifiers allow you to add a delay to the event listener.

1<div data-on-load__delay.500ms="$count = 1"></div>

data-on-signal-patch #

Runs an expression whenever one or more signals are patched. This is useful for tracking changes, updating computed values, or triggering side effects when data updates.

1<div data-on-signal-patch="console.log('A signal changed!')"></div>

The patch variable is available in the expression and contains the signal patch details. You can filter which signals to watch using the data-on-signal-patch-filter attribute.

1<div data-on-signal-patch="console.log('Signal patch:', patch)"
2     data-on-signal-patch-filter="{include: /counter/}"
3></div>

The data-on-signal-patch-filter attribute accepts an object with include and/or exclude properties that can be regular expressions.

1<!-- Only react to counter signal changes -->
2<div data-on-signal-patch-filter="{include: /^counter$/}"></div>
3
4<!-- React to all changes except those ending with "changes" -->
5<div data-on-signal-patch-filter="{exclude: /changes$/}"></div>
6
7<!-- Combine include and exclude filters -->
8<div data-on-signal-patch-filter="{include: /user/, exclude: /password/}"></div>

Modifiers

Modifiers allow you to modify the timing of the event listener.

1<div data-on-signal-patch__debounce.500ms="doSomething()"></div>

data-preserve-attr #

Preserves the value of an attribute when morphing DOM elements.

1<details open data-preserve-attr="open">
2    <summary>Title</summary>
3    Content
4</details>

You can preserve multiple attributes by separating them with a space.

1<details open class="foo" data-preserve-attr="open class">
2    <summary>Title</summary>
3    Content
4</details>

data-ref #

Creates a new signal that is a reference to the element on which the data attribute is placed.

1<div data-ref-foo></div>

The signal name can be specified in the key (as above), or in the value (as below). This can be useful depending on the templating language you are using.

1<div data-ref="foo"></div>

The signal value can then be used to reference the element.

1$foo is a reference to a <span data-text="$foo.tagName"></span> element

Modifiers

Modifiers allow you to modify behavior when defining references.

1<div data-ref-my-signal__case.kebab></div>

data-show #

Shows or hides an element based on whether an expression evaluates to true or false. For anything with custom requirements, use data-class instead.

1<div data-show="$foo"></div>

To prevent flickering of the element before Datastar has processed the DOM, you can add a display: none style to the element to hide it initially.

1<div data-show="$foo" style="display: none"></div>

data-signals #

Patches (adds, updates or removes) one or more signals into the existing signals. Values defined later in the DOM tree override those defined earlier.

1<div data-signals-foo="1"></div>

Signals can be nested using dot-notation.

1<div data-signals-foo.bar="1"></div>

The data-signals attribute can also be used to patch multiple signals using a set of key-value pairs, where the keys represent signal names and the values represent expressions.

1<div data-signals="{foo: {bar: 1, baz: 2}}"></div>

The value above is written in JavaScript object notation, but JSON, which is a subset and which most templating languages have built-in support for, is also allowed.

Setting a signals value to null will remove the signal.

1<div data-signals="{foo: null}"></div>

Keys used in data-signals-* are converted to camel case, so the signal name mySignal must be written as data-signals-my-signal or data-signals="{mySignal: 1}".

Signals beginning with an underscore are not included in requests to the backend by default. You can opt to include them by modifying the value of the filterSignals option.

Signal names cannot begin with nor contain a double underscore (__), due to its use as a modifier delimiter.

Modifiers

Modifiers allow you to modify behavior when patching signals.

1<div data-signals-my-signal__case.kebab="1"
2     data-signals-foo__ifmissing="1"
3></div>

data-text #

Binds the text content of an element to an expression.

1<div data-text="$foo"></div>

Pro Attributes #

The Pro attributes add functionality to the free open source Datastar framework. These attributes are available under a commercial license that helps fund our open source work.

data-animate #Pro

Allows you to animate element attributes over time. Animated attributes are updated reactively whenever signals used in the expression change.

data-custom-validity #Pro

Allows you to add custom validity to an element using an expression. The expression must evaluate to a string that will be set as the custom validity message. If the string is empty, the input is considered valid. If the string is non-empty, the input is considered invalid and the string is used as the reported message.

1<form>
2    <input data-bind-foo name="foo" />
3    <input data-bind-bar name="bar"
4           data-custom-validity="$foo === $bar ? '' : 'Values must be the same.'"
5    />
6    <button>Submit form</button>
7</form>

data-on-raf #Pro

Runs an expression on every requestAnimationFrame event.

1<div data-on-raf="$count++"></div>

Modifiers

Modifiers allow you to modify the timing of the event listener.

1<div data-on-raf__throttle.10ms="$count++"></div>

data-on-resize #Pro

Runs an expression whenever an element’s dimensions change.

1<div data-on-resize="$count++"></div>

Modifiers

Modifiers allow you to modify the timing of the event listener.

1<div data-on-resize__debounce.10ms="$count++"></div>

data-persist #Pro

Persists signals in local storage. This is useful for storing values between page loads.

1<div data-persist></div>

The signals to be persisted can be filtered by providing a value that is an object with include and/or exclude properties that can be regular expressions.

1<div data-persist="{include: /foo/, exclude: /bar/}"></div>

Modifiers

Modifiers allow you to modify the storage target.

1<div data-persist__session></div>

data-query-string #Pro

Syncs query string params to signal values on page load, and syncs signal values to query string params on change.

1<div data-query-string></div>

The signals to be synced can be filtered by providing a value that is an object with include and/or exclude properties that can be regular expressions.

1<div data-query-string="{include: /foo/, exclude: /bar/}"></div>

Modifiers

Modifiers allow you to enable history support.

1<div data-query-string__history></div>

data-replace-url #Pro

Replaces the URL in the browser without reloading the page. The value can be a relative or absolute URL, and is an evaluated expression.

1<div data-replace-url="`/page${page}`"></div>

data-scroll-into-view #Pro

Scrolls the element into view. Useful when updating the DOM from the backend, and you want to scroll to the new content.

1<div data-scroll-into-view></div>

Modifiers

Modifiers allow you to modify scrolling behavior.

1<div data-scroll-into-view__smooth></div>

data-view-transition #Pro

Sets the view-transition-name style attribute explicitly.

1<div data-view-transition="$foo"></div>

Page level transitions are automatically handled by an injected meta tag. Inter-page elements are automatically transitioned if the View Transition API is available in the browser and useViewTransitions is true.

Attribute Casing #

According to the HTML specification, all data-* attributes (not Datastar the framework, but any time a data attribute appears in the DOM) are case in-sensitive, but are converted to camelCase when accessed from JavaScript by Datastar.

Datastar handles casing of data attributes in two ways:

  1. The keys used in attributes that define signals (data-signals-*, data-computed-*, etc.), are converted to camelCase. For example, data-signals-my-signal defines a signal named mySignal. You would use the signal in a Datastar expression as $mySignal.
  2. The keys used by all other attributes are, by default, converted to kebab-case. For example, data-class-text-blue-700 adds or removes the class text-blue-700, and data-on-rocket-launched would react to the event named rocket-launched.

You can use the __case modifier to convert between camelCase, kebab-case, snake_case, and PascalCase, or alternatively use object syntax when available.

For example, if listening for an event called widgetLoaded, you would use data-on-widget-loaded__case.camel.

Aliasing Attributes #

It is possible to alias data-* attributes to a custom alias (data-foo-*, for example) using the bundler. A custom alias should only be used if you have a conflict with a legacy library and data-ignore cannot be used.

We maintain a data-star-* aliased version that can be included as follows.

1<script type="module" src="https://cdn.jsdelivr.net/gh/starfederation/datastar@main/bundles/datastar-aliased.js"></script>

Datastar Expressions #

Datastar expressions used in data-* attributes can parse signals (prefixed with $).

A variable el is available in every Datastar expression, representing the element that the attribute exists on.

1<div id="bar" data-text="$foo + el.id"></div>

Read more about Datastar expressions in the guide.