Datastar Attributes
This is the complete API reference for Datastar attributes used in Laravel Hyper. Datastar provides the reactive foundation that Hyper builds upon. All standard Datastar attributes work seamlessly in Hyper applications.
TIP
This reference covers standard Datastar attributes. For Hyper-specific extensions like data-error, data-for, data-if, and data-navigate, see Hyper Attributes.
Data Binding & Display
data-signals (Datastar)
Initializes reactive signals on an element. Signals are reactive variables that automatically update the UI when their values change.
Syntax:
<div data-signals="{key: value, key2: value2}"></div>Example:
<div data-signals="{count: 0, name: 'John', items: [1, 2, 3]}">
<!-- Signals available to all child elements -->
</div>Hyper Enhancement
Hyper provides the @signals Blade directive for better Laravel integration. See Blade Directives.
data-bind (Datastar)
Creates two-way data binding between a form element and a signal. Changes in either direction sync automatically.
Syntax:
<input data-bind="signalName" />Modifiers:
__case.camel- Convert to camelCase__case.kebab- Convert to kebab-case__case.snake- Convert to snake_case__case.pascal- Convert to PascalCase
Examples:
Text Input:
<input type="text" data-bind="email" />With Auto-Creation:
<!-- Creates 'username' signal if it doesn't exist -->
<input data-bind="username" value="John" />With Case Conversion:
<input data-bind__case.snake="firstName" />
<!-- Binds to 'first_name' signal -->Supported Elements:
<input>(text, number, email, password, etc.)<textarea><select>(single and multiple)<input type="checkbox"><input type="radio"><input type="file">(base64 encoded)
data-text (Datastar)
Sets the text content of an element to a reactive expression. Automatically escapes HTML for XSS protection.
Syntax:
<div data-text="expression"></div>Examples:
Display Signal:
<p data-text="$username"></p>With Expression:
<p data-text="'Hello, ' + $name + '!'"></p>
<p data-text="$count * 2"></p>
<p data-text="$price.toFixed(2)"></p>Conditional Display:
<p data-text="$items.length > 0 ? $items.length + ' items' : 'No items'"></p>XSS Protection
data-text sets textContent, not innerHTML. HTML tags are automatically escaped and displayed as text.
data-html (Hyper)
Sets the HTML content of an element to a reactive expression. Unlike data-text, this renders HTML tags.
Syntax:
<div data-html="expression"></div>Examples:
Render HTML Content:
<div data-html="$richContent"></div>With Markdown Conversion:
<div data-html="$markdownPreview" class="prose"></div>Security
data-html renders content without escaping. Only use with trusted content. For user input, always sanitize on the server:
$safeHtml = strip_tags($userContent, '<p><strong><em><a>');See Also: Display & Binding
data-cloak (Hyper)
Prevents Flash of Unstyled Content (FOUC) by hiding elements until Datastar initializes.
Syntax:
<div data-cloak>
<!-- Content hidden until framework loads -->
</div>Setup Required:
[data-cloak] { display: none !important; }Examples:
Hide Reactive Content:
<div data-cloak data-signals="{show: true}">
<div data-show="$show">
Won't flash before framework initializes
</div>
</div>See Also: Display & Binding
data-attr:* (Datastar)
Sets HTML attributes dynamically based on reactive expressions. Replace * with any attribute name.
Syntax:
<element data-attr:attributeName="expression"></element>Examples:
Dynamic Links:
<a data-attr:href="'/users/' + $userId">Profile</a>Conditional Attributes:
<button data-attr:disabled="$isProcessing">Submit</button>
<img data-attr:src="$avatar || '/default.jpg'" />Data Attributes:
<div data-attr:data-id="$todoId" data-attr:data-status="$status"></div>Multiple Attributes:
<input data-attr:placeholder="$placeholder"
data-attr:maxlength="$maxLength"
data-attr:required="$isRequired" />Conditionals
data-show (Datastar)
Conditionally shows or hides an element using CSS display property. The element remains in the DOM.
Syntax:
<div data-show="condition"></div>Examples:
Basic Conditional:
<div data-show="$isVisible">
This content is conditionally visible
</div>With Complex Logic:
<div data-show="$user && $user.role === 'admin'">
Admin-only content
</div>Toggle Pattern:
<div data-signals="{showDetails: false}">
<button data-on:click="$showDetails = !$showDetails">Toggle</button>
<div data-show="$showDetails">Details content...</div>
</div>Performance
data-show keeps elements in the DOM (just hidden). For conditional rendering that removes elements from the DOM, use Hyper's data-if.
Events
data-on:* (Datastar)
Attaches event listeners to elements. Replace * with any valid DOM event name.
Syntax:
<element data-on:eventName="expression"></element>Available Modifiers:
__prevent- CallspreventDefault()on the event__stop- CallsstopPropagation()on the event__once- Listener fires only once__passive- Passive event listener__debounce.{time}ms- Debounce execution (with optional.leadingor.trailing)__throttle.{time}ms- Throttle execution (with optional.leadingor.notrailing)__window- Attach listener to window__outside- Trigger when event is outside element__viewtransition- Wrap in View Transition API
Examples:
Click Events:
<button data-on:click="$count++">Increment</button>
<button data-on:click="$count = 0">Reset</button>With preventDefault:
<form data-on:submit__prevent="@postx('/submit')">
<button type="submit">Submit</button>
</form>Debounced Input:
<input data-bind="search"
data-on:input__debounce.300ms="@get('/search?q=' + $search)" />Throttled Event:
<div data-on:scroll__throttle.100ms="handleScroll()">
Content...
</div>Multiple Modifiers:
<button data-on:click__once__prevent="handleAction()">
One-time action
</button>Window Events:
<div data-on:resize__window__throttle.250ms="$width = window.innerWidth">
Window width: <span data-text="$width"></span>
</div>Outside Clicks:
<div data-on:click__outside="$dropdownOpen = false">
<div data-show="$dropdownOpen">Dropdown content</div>
</div>Common Events:
data-on:click- Click eventsdata-on:input- Input change eventsdata-on:change- Change eventsdata-on:submit- Form submissiondata-on:keydown/data-on:keyup- Keyboard eventsdata-on:focus/data-on:blur- Focus eventsdata-on:mouseenter/data-on:mouseleave- Mouse events
Key Modifiers (Hyper):
Filter keyboard events by specific keys:
<input data-on:keydown__enter="@postx('/submit')" />
<input data-on:keydown__escape="$editing = false" />
<div data-on:keydown__window__arrow-up="$selectedIndex--"></div>| Modifier | Key |
|---|---|
__enter | Enter/Return |
__escape | Escape |
__space | Spacebar |
__tab | Tab |
__arrow-up, __arrow-down, __arrow-left, __arrow-right | Arrow keys |
__delete, __backspace | Delete/Backspace |
__a - __z, __0 - __9 | Letter/number keys |
__ctrl, __shift, __alt, __meta | System modifier keys |
See Also: Events - Key Modifiers
Styling
data-class:* (Datastar)
Conditionally adds or removes CSS classes based on reactive expressions.
Syntax:
<!-- Single class -->
<div data-class:className="condition"></div>
<!-- Multiple classes (object syntax) -->
<div data-class="{className: condition, className2: condition2}"></div>Examples:
Single Class:
<div data-class:active="$isActive">
Content
</div>Multiple Classes:
<div data-class="{
'bg-green-500': $status === 'success',
'bg-red-500': $status === 'error',
'bg-blue-500': $status === 'info'
}">
Status indicator
</div>Toggle Classes:
<button data-on:click="$expanded = !$expanded"
data-class:rotate-180="$expanded">
Expand ▼
</button>Active Navigation:
<a href="/dashboard"
data-class:active="$currentPage === 'dashboard'">
Dashboard
</a>data-style:* (Datastar)
Sets inline CSS styles dynamically based on reactive expressions.
Syntax:
<div data-style:propertyName="value"></div>Examples:
Dynamic Colors:
<div data-style:background-color="$theme === 'dark' ? '#000' : '#fff'">
Content
</div>Dynamic Dimensions:
<div data-style:width="$progress + '%'"
data-style:height="'20px'">
Progress bar
</div>Conditional Opacity:
<div data-style:opacity="$isLoading ? '0.5' : '1'">
Content
</div>Animation
data-transition (Hyper)
Adds smooth animations when showing/hiding elements with data-show. Supports helper mode, class mode, and collapse mode.
Helper Mode (Style-based):
<div data-show="$visible" data-transition>
Fades and scales smoothly
</div>Helper Modifiers:
__opacity- Opacity transition only__scale- Scale transition only__scale__[value]- Custom scale value (0-100)__duration__[ms]- Duration in milliseconds__delay__[ms]- Delay before starting__origin__[position]- Transform origin__in- Enter animation only__out- Leave animation only
Class Mode (Tailwind CSS):
<div data-show="$visible"
data-transition:enter="transition ease-out duration-300"
data-transition:enter-start="opacity-0 scale-90"
data-transition:enter-end="opacity-100 scale-100"
data-transition:leave="transition ease-in duration-200"
data-transition:leave-start="opacity-100 scale-100"
data-transition:leave-end="opacity-0 scale-90">
Content
</div>Collapse Mode (Height Animation):
<div data-show="$expanded" data-transition__collapse>
Smoothly expands/collapses by height
</div>
<!-- With options -->
<div data-show="$expanded" data-transition__collapse__duration__500__min__50>
500ms duration, 50px minimum height
</div>Collapse Modifiers:
__collapse- Enable collapse mode__duration__[ms]- Animation duration (default: 250ms)__min__[px]- Minimum collapsed height (default: 0)
See Also: Styling - Transitions
Advanced Attributes
data-computed:* (Datastar)
Creates a read-only computed signal that automatically recalculates when dependencies change.
Syntax:
<div data-computed:signalName="expression"></div>Examples:
Shopping Cart Total:
<div data-signals="{items: [{price: 10, qty: 2}, {price: 5, qty: 3}]}"
data-computed:total="$items.reduce((sum, item) => sum + (item.price * item.qty), 0)">
<p data-text="'Total: $' + $total"></p>
</div>Full Name:
<div data-signals="{firstName: 'John', lastName: 'Doe'}"
data-computed:names="$firstName + ' ' + $lastName">
<h1 data-text="$names"></h1>
</div>Filtered List:
<div data-signals="{users: [...], searchTerm: ''}"
data-computed:filteredUsers="$users.filter(u => u.name.includes($searchTerm))">
<p data-text="$filteredUsers.length + ' results'"></p>
</div>TIP
Computed signals are cached and only recalculate when their dependencies change, making them efficient for expensive operations.
data-effect (Datastar)
Executes an expression whenever signals in the expression change. Useful for side effects like logging, analytics, or DOM manipulation.
Syntax:
<div data-effect="expression"></div>Examples:
Console Logging:
<div data-effect="console.log('Count changed:', $count)">
<button data-on:click="$count++">Count: <span data-text="$count"></span></button>
</div>Local Storage Sync:
<div data-effect="localStorage.setItem('theme', $theme)">
<select data-bind="theme">
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
</div>data-ref (Datastar)
Creates a reference to an element that can be accessed .
Syntax:
<element data-ref="referenceName"></element>Examples:
Focus Management:
<div data-signals="{showModal: false}">
<button data-on:click="$showModal = true; $modalInput.focus()">
Open Modal
</button>
<div data-show="$showModal">
<input data-ref="modalInput" />
</div>
</div>Scroll to Element:
<button data-on:click="$section.scrollIntoView({ behavior: 'smooth' })"
class="p-2 bg-blue-500 text-white rounded">
Scroll to Section
</button>
<div style="height: 1000px;"></div>
<div data-ref="section" class="p-5 bg-gray-200 rounded">
Target section content
</div>Element Measurements:
<div data-ref="box"
data-on:click="$width = $box.offsetWidth">
<p data-text="'Width: ' + $width + 'px'"></p>
</div>data-on-intersect (Datastar)
Triggers an expression when an element enters or exits the viewport using IntersectionObserver.
Syntax:
<element data-on-intersect="expression"></element>Modifiers:
__once- Trigger only once__half- Trigger when 50% visible__full- Trigger when 100% visible__threshold.{0-1}- Custom visibility threshold__rootMargin.{value}- Root margin (e.g.,100px)
Examples:
Lazy Loading:
<img data-attr:src="$loaded ? $imageUrl : '/placeholder.jpg'"
data-on-intersect__once="$loaded = true" />Infinite Scroll:
<div data-on-intersect__once="@get('/load-more?page=' + $page++)">
Loading sentinel
</div>Scroll Animations:
<div data-on-intersect__half="$visible = true"
data-class:fade-in="$visible">
Animated content
</div>View Tracking:
<article data-on-intersect__once__half="gtag('event', 'article_viewed', {id: $articleId})">
Article content
</article>data-on-interval (Datastar)
Executes an expression repeatedly at specified intervals.
Syntax:
<element data-on-interval="expression"></element>Modifiers:
__duration.{time}ms- Set interval duration (default: 1000ms)__leading- Execute immediately, then at intervals
Examples:
Auto-Refresh Dashboard:
<div data-on-interval__duration.5000ms="@get('/dashboard/stats')">
<!-- Stats that refresh every 5 seconds -->
</div>Countdown Timer:
<div data-signals="{timeLeft: 60}"
data-on-interval__duration.1000ms="$timeLeft > 0 && $timeLeft--">
<p data-text="'Time remaining: ' + $timeLeft + 's'"></p>
</div>Clock:
<div data-signals="{currentTime: new Date().toLocaleTimeString()}"
data-on-interval__duration.1000ms="$currentTime = new Date().toLocaleTimeString()">
<p data-text="$currentTime"></p>
</div>data-resize (Hyper)
Executes an expression when an element's dimensions change using ResizeObserver.
Syntax:
<div data-resize="expression"></div>Expression receives width and height arguments.
Modifiers:
__document- Observe viewport instead of element__debounce.[time]- Debounce resize events__throttle.[time]- Throttle resize events
Examples:
Track Element Size:
<div data-signals="{w: 0, h: 0}"
data-resize="$w = width; $h = height">
Size: <span data-text="$w"></span> x <span data-text="$h"></span>
</div>Viewport Resize:
<div data-resize__document="$isMobile = width < 768">
<div data-show="$isMobile">Mobile view</div>
<div data-show="!$isMobile">Desktop view</div>
</div>See Also: Refs & Observers - Resize
data-teleport (Hyper)
Renders element content at a different DOM location while maintaining reactivity.
Syntax:
<template data-teleport="selector">
<!-- Content rendered at selector -->
</template>Modifiers:
__prepend- Insert before target__append- Insert after target
Examples:
Modal Pattern:
<template data-teleport="body">
<div data-show="$modalOpen" class="modal">
Modal content rendered at body
</div>
</template>Prepend/Append:
<template data-teleport__prepend="#target">
Inserted before #target
</template>
<template data-teleport__append="#target">
Inserted after #target
</template>See Also: Teleport
data-persist (Hyper)
Automatically persists signal values to localStorage or sessionStorage.
Syntax:
<div data-signals="{count: 0}" data-persist="count"></div>Modifiers:
__session- Use sessionStorage instead of localStorage__as.[key]- Custom storage key__prefix.[name]- Add prefix to storage key
Examples:
Basic Persistence:
<div data-signals="{theme: 'light', count: 0}" data-persist="theme, count">
<!-- theme and count persist across page reloads -->
</div>Session Storage:
<div data-signals="{temp: ''}" data-persist__session="temp">
<!-- Clears when browser closes -->
</div>Custom Key:
<div data-signals="{count: 0}" data-persist__as.mycounter="count">
<!-- Stored as 'mycounter' instead of '_x_count' -->
</div>See Also: Persistence
HTTP Actions
These actions make HTTP requests to your Laravel backend. They automatically send signals in the request and process SSE responses.
Hyper CSRF Protection
Hyper provides CSRF-protected versions: @postx, @putx, @patchx, @deletex. See Blade Directives.
@get(url, options) (Datastar)
Makes a GET request. Signals are sent as query parameters.
Syntax:
<element data-on:event="@get('/endpoint', {options})"></element>Examples:
Basic GET:
<button data-on:click="@get('/api/data')">Load Data</button>With Signal Parameters:
<button data-on:click="@get('/search?q=' + $searchTerm)">Search</button>With Options:
<button data-on:click="@get('/data', {
headers: {'X-Custom-Header': 'value'},
openWhenHidden: true
})">Load</button>@post(url, options) (Datastar)
Makes a POST request. Signals are sent in the request body as JSON.
Syntax:
<element data-on:event="@post('/endpoint', {options})"></element>Examples:
Basic POST:
<form data-on:submit__prevent="@post('/api/submit')">
<input data-bind="name" />
<button type="submit">Submit</button>
</form>CSRF Protection
Use @postx instead for CSRF-protected POST requests in Laravel:
<button data-on:click="@postx('/create')">Create</button>@put(url, options) (Datastar)
Makes a PUT request. Use @putx for CSRF protection.
Example:
<button data-on:click="@putx('/api/update/' + $id)">Update</button>@patch(url, options) (Datastar)
Makes a PATCH request. Use @patchx for CSRF protection.
Example:
<button data-on:click="@patchx('/api/patch/' + $id)">Patch</button>@delete(url, options) (Datastar)
Makes a DELETE request. Use @deletex for CSRF protection.
Example:
<button data-on:click="@deletex('/api/delete/' + $id)">Delete</button>Request Options
All HTTP actions accept an options object with these properties:
{
// Request configuration
contentType: 'json' | 'form', // Default: 'json'
headers: { [key: string]: string }, // Custom headers
// Signal filtering
filterSignals: {
include: RegExp, // Include only matching signals
exclude: RegExp // Exclude matching signals
},
// Advanced options
selector: string, // Form selector for submission
openWhenHidden: boolean, // Keep connection open in background
requestCancellation: boolean // Cancel concurrent requests (default: true)
}Automatic Cancellation
Fetch requests automatically terminate when their initiating element is removed from the DOM. This prevents memory leaks and unnecessary network activity when components unmount.
Examples:
Filter Signals:
<button data-on:click="@post('/submit', {
filterSignals: {
include: /^form\./,
exclude: /^temp/
}
})">Submit Form Data Only</button>Custom Headers:
<button data-on:click="@get('/api/data', {
headers: {
'X-API-Key': $apiKey,
'X-Client-Version': '1.0'
}
})">Load</button>Form Content Type:
<button data-on:click="@post('/upload', {
contentType: 'form'
})">Upload</button>Expression Context
All Datastar expressions have access to these special variables:
$signalName- Access any signal (prefix with$)$$refs- Object containing alldata-refelements$$signals- Object containing all signals (for debugging)el- Current element (available in event handlers)event- Event object (in event handlers)
Example:
<div data-on:click="console.log('Element:', el, 'Event:', event, 'All signals:', $$signals)">
Debug Click
</div>Learn More
- Hyper Attributes - Hyper-specific extensions
- Blade Directives - Laravel integration helpers
- Signals - Working with reactive signals
- Events - Event handling patterns
- Official Datastar Docs - Complete Datastar reference
