putyourlightson/laravel-datastar

A reactive hypermedia framework for Laravel.

1.0.0-beta.1 2025-01-13 14:17 UTC

This package is auto-updated.

Last update: 2025-01-13 19:38:28 UTC


README

Stable Version Total Downloads

Datastar Package for Laravel

A reactive hypermedia framework for Laravel.

Warning

This package is in beta and its API may change.

This package integrates the Datastar hypermedia framework with Laravel, allowing you to create reactive frontends driven by Blade views or controllers. It aims to replace the need for front-end frameworks such as React, Vue.js and Alpine.js + htmx, and instead lets you manage state and use logic from your Laravel backend.

Use-cases:

  • Live search and filtering
  • Loading more elements / Infinite scroll
  • Paginating, ordering and filtering lists
  • Submitting forms and running actions
  • Pretty much anything to do with reactive front-ends

License

This package is licensed for free under the MIT License.

Requirements

This package requires Laravel 11.0.0 or later.

Installation

Install manually using composer.

composer require putyourlightson/laravel-datastar:^1.0.0-beta.1

Overview

The Datastar package for Laravel allows you to handle backend requests by sending SSE events using Blade directives in views or using controllers. The former requires less setup and is more straightforward, while the latter provides more flexibility.

Here’s a trivial example that toggles some backend state using the Blade view _datastar/toggle.blade.php to handle the request.

<div data-signals-enabled="false">
    <div data-text="$enabled ? 'ON' : 'OFF'"></div>
    <button data-on-click="{{ datastar()->get('_datastar/toggle') }}">
        <span id="button-text">Enable</span>
    </button>
</div>
{{-- _datastar/toggle.blade.php --}}

@php
    $enabled = $signals->enabled;
    // Do something with the state and toggle the enabled state.
    $enabled = !$enabled;
@endphp

@mergesignals(['enabled' => $enabled])

@mergefragments
    <span id="button-text">
        {{ $enabled ? 'Disable' : 'Enable' }}
    </span>
@endmergefragments

Usage

Start by reading the Getting Started guide to learn how to use Datastar on the frontend. The Datastar package for Laravel only handles backend requests.

Note

The Datastar VSCode extension and IntelliJ plugin have autocomplete for all data-* attributes.

When working with signals, note that you can convert a PHP array into a JSON object using the json_encode function.

@php
    $signals = ['foo' => 1, 'bar' => 2];
@endphp

<div data-signals="{{ json_encode($signals) }}"></div>

Datastar Helper

The datastar() helper function is available in Blade views and returns a Datastar helper that can be used to generate action requests to the Datastar controller. The Datastar controller renders a view containing one or Blade directives that each send an SSE event. Signals are also sent as part of the request, and are made available in Datastar views using the $signals variable.

datastar()->get()

Returns a @get() action request to render a view at the given path.

{{ datastar()->get('path/to/view') }}

datastar()->post()

Works the same as datastar()->get() but returns a @post() action request to render a view at the given path. A CSRF token is automatically generated and sent along with the request.

{{ datastar()->post('path/to/view') }}

datastar()->put()

Works the same as datastar()->post() but returns a @put() action request.

{{ datastar()->put('path/to/view') }}

datastar()->patch()

Works the same as datastar()->post() but returns a @patch() action request.

{{ datastar()->patch('path/to/view') }}

datastar()->delete()

Works the same as datastar()->post() but returns a @delete() action request.

{{ datastar()->delete('path/to/view') }}

Blade Directives

@mergefragments

Merges one or more fragments into the DOM.

@mergefragments
    <div id="new-fragment">New fragment</div>
@endmergefragments

@removefragments

Removes one or more HTML fragments that match the provided selector from the DOM.

@removefragments('#old-fragment')

@mergesignals

Updates the signals with new values.

@mergesignals(['foo' => 1, 'bar' => 2])

@removesignals

Removes signals that match one or more provided paths.

@removesignals(['foo', 'bar'])

@executescript

Executes JavaScript in the browser.

@executescript
    alert('Hello, world!');
@endexecutescript

Using Controllers

You can send SSE events using your own controller instead of a Blade view using the DatastarEventStream trait. Return the getStreamedResponse() method, passing a callable into it that sends zero or more SSE events using methods provided.

// routes/web.php

use App\Http\Controllers\MyController;

Route::resource('/my-controller', MyController::class);
<?php

namespace App\Http\Controllers;

use Illuminate\Routing\Controller;
use Putyourlightson\Datastar\DatastarEventStream;
use Symfony\Component\HttpFoundation\StreamedResponse;

class MyController extends Controller
{
    use DatastarEventStream;

    public function index(): StreamedResponse
    {
        return $this->getStreamedResponse(function() {
            $signals = $this->getSignals();
            $this->mergeSignals(['enabled' => $signals->enabled ? false : true]);
            $this->mergeFragments('
                <span id="button-text">' . ($signals->enabled ? 'Enable' : 'Disable') . '</span>
            ');
        });
    }
}

DatastarEventStream Trait

mergeFragments()

Merges one or more fragments into the DOM.

$this->mergeFragments('<div id="new-fragment">New fragment</div>');

removeFragments()

Removes one or more HTML fragments that match the provided selector from the DOM.

$this->removeFragments('#old-fragment');

mergeSignals()

Updates the signals with new values.

$this->mergeSignals(['foo' => 1, 'bar' => 2]);

removeSignals()

Removes signals that match one or more provided paths.

$this->removeSignals(['foo', 'bar']);

executeScript()

Executes JavaScript in the browser.

$this->executeScript('alert("Hello, world!")');

Signals

When working with signals, either in views rendered by the Datastar controller or by calling $this->getSignals(), you are working with a Signals model, which provides a simple way to manage signals.

@php
    // Getting signal values.
    $username = $signals->username;
    $username = $signals->get('username');
    $username = $signals->get('user.username');
    
    // Setting signal values.
    $username = $signals->username('bobby');
    $username = $signals->set('username', 'bobby');
    $username = $signals->set('user.username', 'bobby');
    $username = $signals->setValues(['user.username' => 'bobby', 'success' => true]);
    
    // Removing signal values.
    $username = $signals->remove('username');
    $username = $signals->remove('user.username');
@endphp

Note

Signals updates cannot be wrapped in {% mergefragment %} tags, since each update creates a server-sent event which will conflict with the fragment’s contents.

Created by PutYourLightsOn.