Skip to content

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:

blade
<div data-signals="{key: value, key2: value2}"></div>

Example:

blade
<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:

blade
<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:

blade
<input type="text" data-bind="email" />

With Auto-Creation:

blade
<!-- Creates 'username' signal if it doesn't exist -->
<input data-bind="username" value="John" />

With Case Conversion:

blade
<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:

blade
<div data-text="expression"></div>

Examples:

Display Signal:

blade
<p data-text="$username"></p>

With Expression:

blade
<p data-text="'Hello, ' + $name + '!'"></p>
<p data-text="$count * 2"></p>
<p data-text="$price.toFixed(2)"></p>

Conditional Display:

blade
<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-attr:* (Datastar)

Sets HTML attributes dynamically based on reactive expressions. Replace * with any attribute name.

Syntax:

blade
<element data-attr:attributeName="expression"></element>

Examples:

Dynamic Links:

blade
<a data-attr:href="'/users/' + $userId">Profile</a>

Conditional Attributes:

blade
<button data-attr:disabled="$isProcessing">Submit</button>
<img data-attr:src="$avatar || '/default.jpg'" />

Data Attributes:

blade
<div data-attr:data-id="$todoId" data-attr:data-status="$status"></div>

Multiple Attributes:

blade
<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:

blade
<div data-show="condition"></div>

Examples:

Basic Conditional:

blade
<div data-show="$isVisible">
    This content is conditionally visible
</div>

With Complex Logic:

blade
<div data-show="$user && $user.role === 'admin'">
    Admin-only content
</div>

Toggle Pattern:

blade
<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:

blade
<element data-on:eventName="expression"></element>

Available Modifiers:

  • __prevent - Calls preventDefault() on the event
  • __stop - Calls stopPropagation() on the event
  • __once - Listener fires only once
  • __passive - Passive event listener
  • __debounce.{time}ms - Debounce execution (with optional .leading or .trailing)
  • __throttle.{time}ms - Throttle execution (with optional .leading or .notrailing)
  • __window - Attach listener to window
  • __outside - Trigger when event is outside element
  • __viewtransition - Wrap in View Transition API

Examples:

Click Events:

blade
<button data-on:click="$count++">Increment</button>
<button data-on:click="$count = 0">Reset</button>

With preventDefault:

blade
<form data-on:submit__prevent="@postx('/submit')">
    <button type="submit">Submit</button>
</form>

Debounced Input:

blade
<input data-bind="search"
       data-on:input__debounce.300ms="@get('/search?q=' + $search)" />

Throttled Event:

blade
<div data-on:scroll__throttle.100ms="handleScroll()">
    Content...
</div>

Multiple Modifiers:

blade
<button data-on:click__once__prevent="handleAction()">
    One-time action
</button>

Window Events:

blade
<div data-on:resize__window__throttle.250ms="$width = window.innerWidth">
    Window width: <span data-text="$width"></span>
</div>

Outside Clicks:

blade
<div data-on:click__outside="$dropdownOpen = false">
    <div data-show="$dropdownOpen">Dropdown content</div>
</div>

Common Events:

  • data-on:click - Click events
  • data-on:input - Input change events
  • data-on:change - Change events
  • data-on:submit - Form submission
  • data-on:keydown / data-on:keyup - Keyboard events
  • data-on:focus / data-on:blur - Focus events
  • data-on:mouseenter / data-on:mouseleave - Mouse events

Styling

data-class:* (Datastar)

Conditionally adds or removes CSS classes based on reactive expressions.

Syntax:

blade
<!-- Single class -->
<div data-class:className="condition"></div>

<!-- Multiple classes (object syntax) -->
<div data-class="{className: condition, className2: condition2}"></div>

Examples:

Single Class:

blade
<div data-class:active="$isActive">
    Content
</div>

Multiple Classes:

blade
<div data-class="{
    'bg-green-500': $status === 'success',
    'bg-red-500': $status === 'error',
    'bg-blue-500': $status === 'info'
}">
    Status indicator
</div>

Toggle Classes:

blade
<button data-on:click="$expanded = !$expanded"
        data-class:rotate-180="$expanded">
    Expand ▼
</button>

Active Navigation:

blade
<a href="/dashboard"
   data-class:active="$currentPage === 'dashboard'">
    Dashboard
</a>

data-style:* (Datastar)

Sets inline CSS styles dynamically based on reactive expressions.

Syntax:

blade
<div data-style:propertyName="value"></div>

Examples:

Dynamic Colors:

blade
<div data-style:background-color="$theme === 'dark' ? '#000' : '#fff'">
    Content
</div>

Dynamic Dimensions:

blade
<div data-style:width="$progress + '%'"
     data-style:height="'20px'">
    Progress bar
</div>

Conditional Opacity:

blade
<div data-style:opacity="$isLoading ? '0.5' : '1'">
    Content
</div>

Advanced Attributes

data-computed:* (Datastar)

Creates a read-only computed signal that automatically recalculates when dependencies change.

Syntax:

blade
<div data-computed:signalName="expression"></div>

Examples:

Shopping Cart Total:

blade
<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:

blade
<div data-signals="{firstName: 'John', lastName: 'Doe'}"
     data-computed:names="$firstName + ' ' + $lastName">

    <h1 data-text="$names"></h1>
</div>

Filtered List:

blade
<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:

blade
<div data-effect="expression"></div>

Examples:

Console Logging:

blade
<div data-effect="console.log('Count changed:', $count)">
    <button data-on:click="$count++">Count: <span data-text="$count"></span></button>
</div>

Local Storage Sync:

blade
<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:

blade
<element data-ref="referenceName"></element>

Examples:

Focus Management:

blade
<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:

blade
<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:

blade
<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:

blade
<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:

blade
<img data-attr:src="$loaded ? $imageUrl : '/placeholder.jpg'"
     data-on-intersect__once="$loaded = true" />

Infinite Scroll:

blade
<div data-on-intersect__once="@get('/load-more?page=' + $page++)">
    Loading sentinel
</div>

Scroll Animations:

blade
<div data-on-intersect__half="$visible = true"
     data-class:fade-in="$visible">
    Animated content
</div>

View Tracking:

blade
<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:

blade
<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:

blade
<div data-on-interval__duration.5000ms="@get('/dashboard/stats')">
    <!-- Stats that refresh every 5 seconds -->
</div>

Countdown Timer:

blade
<div data-signals="{timeLeft: 60}"
     data-on-interval__duration.1000ms="$timeLeft > 0 && $timeLeft--">
    <p data-text="'Time remaining: ' + $timeLeft + 's'"></p>
</div>

Clock:

blade
<div data-signals="{currentTime: new Date().toLocaleTimeString()}"
     data-on-interval__duration.1000ms="$currentTime = new Date().toLocaleTimeString()">
    <p data-text="$currentTime"></p>
</div>

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:

blade
<element data-on:event="@get('/endpoint', {options})"></element>

Examples:

Basic GET:

blade
<button data-on:click="@get('/api/data')">Load Data</button>

With Signal Parameters:

blade
<button data-on:click="@get('/search?q=' + $searchTerm)">Search</button>

With Options:

blade
<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:

blade
<element data-on:event="@post('/endpoint', {options})"></element>

Examples:

Basic POST:

blade
<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:

blade
<button data-on:click="@postx('/create')">Create</button>

@put(url, options) (Datastar)

Makes a PUT request. Use @putx for CSRF protection.

Example:

blade
<button data-on:click="@putx('/api/update/' + $id)">Update</button>

@patch(url, options) (Datastar)

Makes a PATCH request. Use @patchx for CSRF protection.

Example:

blade
<button data-on:click="@patchx('/api/patch/' + $id)">Patch</button>

@delete(url, options) (Datastar)

Makes a DELETE request. Use @deletex for CSRF protection.

Example:

blade
<button data-on:click="@deletex('/api/delete/' + $id)">Delete</button>

Request Options

All HTTP actions accept an options object with these properties:

typescript
{
    // 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:

blade
<button data-on:click="@post('/submit', {
    filterSignals: {
        include: /^form\./,
        exclude: /^temp/
    }
})">Submit Form Data Only</button>

Custom Headers:

blade
<button data-on:click="@get('/api/data', {
    headers: {
        'X-API-Key': $apiKey,
        'X-Client-Version': '1.0'
    }
})">Load</button>

Form Content Type:

blade
<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 all data-ref elements
  • $$signals - Object containing all signals (for debugging)
  • el - Current element (available in event handlers)
  • event - Event object (in event handlers)

Example:

blade
<div data-on:click="console.log('Element:', el, 'Event:', event, 'All signals:', $$signals)">
    Debug Click
</div>

Learn More