Blade Fragments

Send only the parts of your views that changed.

Overview

Blade Fragments let you define named sections within your views that can be rendered independently. Instead of sending an entire view, you send just the fragment that changed.

This is more efficient than full view rendering and keeps your templates DRY—the same view works for both full page loads and partial updates.

Defining Fragments

Use the @fragment directive to mark sections of your Blade views:

<!-- resources/views/posts/index.blade.php -->

<div class="posts-page">
    <h1>Posts</h1>

    @fragment('posts-list')
    <div id="posts-list">
        @foreach($posts as $post)
            <article class="post">
                <h2>{{ $post->title }}</h2>
                <p>{{ $post->excerpt }}</p>
            </article>
        @endforeach
    </div>
    @endfragment

    @fragment('pagination')
    <nav id="pagination">
        {{ $posts->links() }}
    </nav>
    @endfragment
</div>
Fragment Naming
Use descriptive, kebab-case names for fragments. The name should indicate what the fragment contains.

Rendering Fragments

Single Fragment

Use fragment() to render and patch a single fragment:

return gale()
    ->fragment('posts.index', 'posts-list', [
        'posts' => Post::paginate(10),
    ]);

The three arguments are:

  1. View name — The Blade view containing the fragment
  2. Fragment name — The name used in @fragment('name')
  3. Data — Variables to pass to the view

With Options

Pass options to control where and how the fragment is patched:

return gale()
    ->fragment('posts.index', 'posts-list', $data, [
        'selector' => '#posts-list',  // Target element
        'mode' => 'morph',            // Update mode
    ]);

Multiple Fragments

Use fragments() to send multiple fragments in a single response:

return gale()
    ->fragments([
        [
            'view' => 'posts.index',
            'fragment' => 'posts-list',
            'data' => compact('posts'),
            'options' => ['selector' => '#posts-list'],
        ],
        [
            'view' => 'posts.index',
            'fragment' => 'pagination',
            'data' => compact('posts'),
            'options' => ['selector' => '#pagination'],
        ],
    ]);

Each fragment is sent as its own SSE event, allowing the browser to update multiple sections efficiently.

View Macro

Gale adds a renderFragment macro to Laravel's View facade for getting fragment HTML directly:

use Illuminate\Support\Facades\View;

$html = View::renderFragment('posts.index', 'posts-list', [
    'posts' => $posts,
]);

// Returns the rendered HTML string

This is useful when you need the fragment HTML for other purposes, like caching or testing.

Nested Fragments

Fragments can be nested inside each other:

@fragment('sidebar')
<aside id="sidebar">
    <h3>Categories</h3>

    @fragment('category-list')
    <ul id="category-list">
        @foreach($categories as $category)
            <li>{{ $category->name }}</li>
        @endforeach
    </ul>
    @endfragment
</aside>
@endfragment

You can render either fragment independently:

// Render just the category list
return gale()->fragment('layout', 'category-list', compact('categories'));

// Or render the entire sidebar including the list
return gale()->fragment('layout', 'sidebar', compact('categories'));

Practical Example

Here's a complete example of a search page with fragments:

The View

<!-- resources/views/products/search.blade.php -->
<div class="search-page"
     x-data="{ query: '' }">

    <input type="text"
           x-model="query"
           @input.debounce.300ms="$postx('/products/search')"
           placeholder="Search products...">

    @fragment('results')
    <div id="results" x-loading.class="opacity-50">
        @forelse($products as $product)
            <div class="product">
                <h3>{{ $product->name }}</h3>
                <p>{{ $product->price }}</p>
            </div>
        @empty
            <p>No products found.</p>
        @endforelse
    </div>
    @endfragment

    @fragment('count')
    <p id="count">
        Showing {{ $products->count() }} of {{ $products->total() }} products
    </p>
    @endfragment
</div>

The Controller

public function search()
{
    $query = request()->state('query', '');
    $products = Product::search($query)->paginate(20);

    return gale()
        ->fragment('products.search', 'results', compact('products'), [
            'selector' => '#results',
        ])
        ->fragment('products.search', 'count', compact('products'), [
            'selector' => '#count',
        ]);
}

Why Use Fragments?

DRY Templates

One view file serves both full pages and partial updates.

Efficient

Send only what changed, not the entire page.

Maintainable

Logic stays together—no duplicate partials.

Progressive

Works without JavaScript—full page loads still work.

Quick Reference

Method/Directive Description
@fragment('name') Start a named fragment section
@endfragment End the fragment section
gale()->fragment($view, $name, $data) Render and send a fragment
gale()->fragments([...]) Send multiple fragments
View::renderFragment($view, $name, $data) Render fragment to HTML string

On this page