Anybody using spatie/laravel-query-builder with Livewire?

Hi!

Is anybody using spatie/laravel-query-builder with Livewire?

If so, how did you make it all work together?

1 Like

Out of curiosity, is there an advantage you found for using it (within livewire)? I looked at it briefly when I was trying to find an easier solution to Passing an Eloquent (or query) Builder as a parameter, but quickly moved on because it was no help there. From the little I read, I remember thinking that it seemed like a great package for highly dynamic api endpoints, but for anything else I didn’t think the added benefit outweighed the added configuration. But again, I didn’t look to deep, and I’m always happy to be proven wrong.

I would also like to know this. How to set this up so that laravel query builder features can be used with Livewire without reloading the page.

Because as I see now, these two do not work together with subsequent requests from livewire.

I have it working but it is hacky :smiley:
It works with query update and filters the results.

On the component:

public $filter = [];
protected $updatesQueryString = ['filter']; 

 return view('livewire.items', [
            'items' => new (ItemsQuery($this->filter))->paginate()
        ]);

Then I have query class:

class ItemsQuery extends \Spatie\QueryBuilder\QueryBuilder
{
    public function __construct(array $filter = [])
    {
 request()->query->set('filter', $filter);

$query = Item::query()
 parent::__construct($query, request());
        $this->request->query->set('filter', $filter);

$this->allowedFilters(....);
}
}
1 Like

I use this at the moment.

<?php

namespace App\Http\Livewire;

use App\Item;
use Livewire\Component;
use Spatie\QueryBuilder\QueryBuilderRequest;

class Table extends Component
{
    /** @var QueryBuilderRequest */
    protected $request;

    /** @var array<string,string> */
    public $filter = [];

    /** @var array<string> */
    protected $updatesQueryString = [
        'filter',
    ];

    public function mount(): void
    {
        $this->filter = $this->request()->query('filter', $this->filter);
    }

    public function request(): QueryBuilderRequest
    {
        if (!$this->request) {
            $this->request = app(QueryBuilderRequest::class);
        }

        return $this->request;
    }

    public function filter(string $filter, ?string $slug): void
    {
        if (is_null($slug)) {
            unset($this->filter[$filter]);
        } else {
            $this->filter[$filter] = $slug;
        }

        $this->request()->query->set('filter', $this->filter);
    }

    public function render(): View
    {
        $items = QueryBuilder::for(Item::query(), $this->request())
            ->get();

        return view('livewire.table', [
            'items' => $items,
        ]);
    }
}

And in my filter views I use:

<a role="button" href="#" wire:click.prevent="filter('filter-name', 'filter-value')">Filter!</a>
2 Likes

Thanks guys, that are two possible implementations were we could start with.

Great to hear we do not have to drop the great Query Builder package from Spatie!

Hi did you manage to make this reactive? I followed official tutorials for simple index page with a table and tried hacks above.
For some reason, when I type in an input field to filter by name, it does not update results, and on the deletion of the query string, it does not refresh the results. only page refresh does show the query string results correctly.
If I have a regular eloquent query or raw SQL in my component, it works perfect, but with the Spatie query builder, it is laggy and not reactive

Can you show us your code?

Because all what Spatie Query Builder does is getting results, notting fancy that could make Livewire reactivity break.

I for once debugged this for an hour or so:

function calcData(){
  return $data;
}

Where it should be:

function calcData(){
  $this->data  = $data;
}

Had a good laugh after catching that! :rofl: