kadevland/laravel-htmx-helpers

Native Laravel HTMX helpers for Request and Response objects - no external dependencies

Installs: 1

Dependents: 0

Suggesters: 0

Security: 0

Stars: 2

Watchers: 0

Forks: 0

Open Issues: 0

pkg:composer/kadevland/laravel-htmx-helpers

v1.0.0 2025-09-23 21:53 UTC

This package is auto-updated.

Last update: 2025-09-30 18:22:33 UTC


README

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status Total Downloads

Native Laravel HTMX helpers for Request and Response objects with zero external dependencies. This package provides a clean, Laravel-native way to work with HTMX without requiring any third-party HTMX packages.

Why This Package?

  • ๐Ÿš€ Zero Dependencies: Uses only Laravel's native Request/Response macros
  • ๐Ÿงช Fully Tested: Comprehensive Pest test suite
  • ๐Ÿ“š Well Documented: Clear examples and use cases
  • ๐Ÿ”ง Framework Native: Integrates seamlessly with Laravel 11+ (requires @fragment support)
  • ๐ŸŽฏ Type Safe: Full TypeScript-style PHP declarations
  • โšก Lightweight: Minimal overhead and performance impact

Requirements

  • PHP 8.2+
  • Laravel 11+ (for native @fragment directive support)

Installation

You can install the package via composer:

composer require kadevland/laravel-htmx-helpers

The package will auto-register itself via Laravel's package discovery.

Optionally, you can publish the config file:

php artisan vendor:publish --tag="htmx-helpers-config"

Usage

Request Macros

Detecting HTMX Requests

use Illuminate\Http\Request;

public function handle(Request $request)
{
    if ($request->isHtmxRequest()) {
        // Handle HTMX request
        return view('partial.content')->fragment('main-content');
    }

    // Handle regular request
    return view('full.page');
}

Getting HTMX Request Information

// Check if request is boosted
if ($request->isHtmxBoosted()) {
    // Handle boosted request
}

// Get current URL from HTMX
$currentUrl = $request->htmxCurrentUrl();

// Check if it's a history restore request
if ($request->isHtmxHistoryRestoreRequest()) {
    // Handle history restore
}

// Get prompt response
$userInput = $request->htmxPrompt();

// Get target and trigger information
$target = $request->htmxTarget();        // "#main-content"
$trigger = $request->htmxTrigger();      // "#submit-button"
$triggerName = $request->htmxTriggerName(); // "my-trigger"

Response Macros

Basic HTMX Responses

use Illuminate\Support\Facades\Response;

// Redirect the browser
return Response::htmxRedirect('/dashboard');

// Refresh the current page
return Response::htmxRefresh();

// Push a new URL to browser history
return Response::htmxPushUrl('/new-url');

// Replace current URL in browser history
return Response::htmxReplaceUrl('/updated-url');

Advanced HTMX Responses

// Client-side location (can include additional data)
return Response::htmxLocation([
    'path' => '/users',
    'target' => '#main-content',
    'swap' => 'innerHTML'
]);

// Override swap method
return Response::htmxReswap('outerHTML');

// Override target element
return Response::htmxRetarget('#different-target');

// Override selector
return Response::htmxReselect('.new-selector');

Event Triggering

// Trigger single event
return Response::htmxTrigger('userUpdated');

// Trigger multiple events with data
return Response::htmxTrigger([
    'userUpdated' => ['id' => 123],
    'showNotification' => 'User saved successfully'
]);

// Trigger events after settle
return Response::htmxTriggerAfterSettle('dataLoaded');

// Trigger events after swap
return Response::htmxTriggerAfterSwap('contentSwapped');

Multiple Fragments (Out-of-Band Swaps)

// Send multiple fragments in one response using Laravel native methods
return view('admin.users.index', compact('users', 'stats'))
    ->fragments(['user-list', 'user-stats', 'notifications']);

// Or conditionally send fragments
return view('admin.users.index', compact('users', 'stats'))
    ->fragmentsIf($request->isHtmxRequest(), ['user-list', 'user-stats']);

Polling Control

// Stop HTMX polling (returns 286 status code)
return Response::htmxStopPolling();

Laravel Blade Integration

This package works seamlessly with Laravel 11+'s native @fragment directive:

// Controller
public function update(Request $request, User $user)
{
    $user->update($request->validated());

    if ($request->isHtmxRequest()) {
        return response(
            view('users.edit', compact('user'))->fragment('user-form')
        );
    }

    return redirect()->route('users.show', $user);
}
<!-- Blade template: users/edit.blade.php -->
@fragment('user-form')
    <form hx-put="/users/{{ $user->id }}" hx-target="#user-form" hx-swap="outerHTML">
        <!-- form fields -->
        <div class="success-message">User updated successfully!</div>
    </form>
@endfragment

Real-World Examples

1. Form Submission with Validation

public function store(CreateUserRequest $request)
{
    try {
        $user = User::create($request->validated());

        if ($request->isHtmxRequest()) {
            return response(
                view('users.create', [
                    'message' => 'User created successfully!',
                    'user' => $user
                ])->fragment('form-response')
            );
        }

        return redirect()->route('users.index')
            ->with('success', 'User created!');

    } catch (ValidationException $e) {
        if ($request->isHtmxRequest()) {
            return response(
                view('users.create', [
                    'errors' => $e->errors()
                ])->fragment('form-errors'),
                422
            );
        }

        return back()->withErrors($e->errors())->withInput();
    }
}

2. Dynamic Content Loading

public function loadUserPosts(Request $request, User $user)
{
    $posts = $user->posts()->paginate(10);

    // Using Laravel's native fragmentIf method
    return view('users.show', compact('user', 'posts'))
        ->fragmentIf($request->isHtmxRequest(), 'posts-list');
}

3. Search with Live Results

public function search(Request $request)
{
    $query = $request->get('q');
    $results = User::where('name', 'like', "%{$query}%")->get();

    // Using Laravel's native fragmentIf method
    return view('search.index', compact('results'))
        ->fragmentIf($request->isHtmxRequest(), 'search-results');
}

Configuration

// config/htmx-helpers.php
return [
    'enabled' => env('HTMX_HELPERS_ENABLED', true),

    'headers' => [
        'default_swap' => 'innerHTML',
        'auto_csrf' => env('HTMX_AUTO_CSRF', true),
    ],

    'debug' => [
        'log_requests' => env('HTMX_LOG_REQUESTS', false),
        'debug_headers' => env('HTMX_DEBUG_HEADERS', false),
    ],
];

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

Contributing

Please see CONTRIBUTING for details.

Security Vulnerabilities

Please report security vulnerabilities via email to contact@kadevland.net.

Credits

License

The MIT License (MIT). Please see License File for more information.

Related Packages

Why Not Use mauricius/laravel-htmx?

The mauricius/laravel-htmx package is excellent, but this package offers:

  1. Zero Dependencies: No external package dependencies
  2. Laravel Native: Uses only Laravel's macro system
  3. Lightweight: Minimal footprint
  4. Framework Integration: Designed specifically for Laravel 11+ features (native @fragment support)
  5. Simplicity: Just the macros you need, nothing more

Choose this package if you want a minimal, dependency-free solution. Choose mauricius/laravel-htmx if you need advanced HTMX features like middleware, validation helpers, etc.