vincent15000's avatar

HTMX and blade fragment

Hello,

I'm trying to use HTMX (first time).

I have followed the dedicated HTMX series on Laracast, but it doesn't work.

https://laracasts.com/series/crafting-web-applications-with-htmx

Here what I'm doing.

// view

{{ $category }}

<div
    hx-get="/hello"
    hx-target="#hello"    
>
    All categories
</div>


@fragment('hello')
    <div id="hello">
        @if (isset($items))
            @foreach ($items as $item)
                <div>{{ $item->name }}</div>
            @endforeach
        @endif
    </div>
@endfragment

// controller

public function hello(Request $request)
{
    $items = Category::all();

    return view('tables.page', compact('items'))->fragmentIf($request->hasHeader('Hx-Request'), 'hello');
}

And I get this error.

Undefined variable $category

As it's an HX request (checked !), Laravel should only return the fragment view and thanks to hx-target, only the target part of the view should be rerendered (so no need to have the $category variable.

Hmmm ... what am I doing wrong ?

Thanks for your help.

V

0 likes
5 replies
martinbean's avatar
Level 80

@vincent15000 You have {{ $category }} as the very first line of your view, but you don’t pass a variable named category to your view in your controller. You query categories, but then assign them to a variable called $items instead, and pass that to your view.

1 like
vincent15000's avatar

@martinbean Hello, thank you for your response.

Hmmm ... it's just an example, my view is more complex.

For the first load, all work fine and the $category is displayed.

Then when I click on the link to trigger an HX request, it's another function called from the controller.

public $categoryService;

public function __construct(CategoryService $categoryService)
{
    $this->categoryService = $categoryService;
}

public function page(Request $request)
{
    Gate::authorize('viewAny', Category::class);

    $categories = $this->categoryService->index();

    $category = $request->category ? Category::find($category) : null;

    return view('tables.page', compact('categories', 'category'));
}

public function hello(Request $request)
{
    $items = Category::all();

    return view('tables.page', compact('items'))->fragment('hello');
}

For the HX request, the variable is called $items just to not re-use the same variable as in the page() function.

vincent15000's avatar

@martinbean I just understood ... Laravel generates the whole page, so it needs all variables, but next step it extracts only the fragment part of the view and send it to the browser.

Is there a way to avoid generating the whole page and just generate the isolated fragment ?

UPDATED => the solution is to create blade fragments in separate views. And this way, no need to specify which fragment, because the fragment is defined in a separate view.

martinbean's avatar

Hmmm ... it's just an example, my view is more complex.

@vincent15000 This is why it’s always better to send the actual problem code instead of making up code examples. You make people waste time trying to find a bug that isn’t even there.

Laravel generates the whole page, so it needs all variables, but next step it extracts only the fragment part of the view and send it to the browser.

It makes sense. Laravel needs to render the template to be able to find and extract the portion requested.

1 like
vincent15000's avatar

@martinbean I don't think that I make people waste time.

If I have posted the code, it's really because I thought I had done something wrong in my code.

Please or to participate in this conversation.