protonemedia / inertiajs-tables-laravel-query-builder

Inertia.js Tables for Laravel Query Builder
https://protone.media/en/blog/introducing-inertiajs-tables-a-datatables-like-package-for-laravel-query-builder
MIT License
438 stars 124 forks source link

QueryBuilder error on search #24

Closed BKirev closed 2 years ago

BKirev commented 3 years ago

Hey there,

Users are displayed properly in the table, but I'm getting the following error when I type something in the search field: Argument 1 passed to Spatie\QueryBuilder\QueryBuilder::Spatie\QueryBuilder\Concerns\{closure}() must be of the type string, array given

Using the example controller:

            ->defaultSort('name')
            ->allowedSorts(['name', 'email'])
            ->allowedFilters(['name', 'email', $globalSearch])
            ->paginate()
            ->withQueryString();

as well as the example page component with the table from the README.

Vue 3, Laravel Jetstream(Inertia).

donmbelembe commented 3 years ago

show everything in this action

BKirev commented 3 years ago

UserController

public function index()
    {
        $globalSearch = AllowedFilter::callback('global', function ($query, $value) {
            $query->where(function ($query) use ($value) {
                $query->where('name', 'LIKE', "%{$value}%")->orWhere('email', 'LIKE', "%{$value}%");
            });
        });

        $users = QueryBuilder::for(User::class)
            ->defaultSort('name')
            ->allowedSorts(['name', 'email'])
            ->allowedFilters(['name', 'email', $globalSearch])
            ->paginate()
            ->withQueryString();

        return Inertia::render('Admin/Users', [
            'users' => $users,
        ])->table(function (InertiaTable $table) {
            $table->addSearchRows([
                'name' => 'Name',
                'email' => 'Email address',
            ])->addColumns([
                'email' => 'Email address',
            ]);
        });
    }

Users.vue

<template>
    <admin-layout>
        <Table
            :filters="queryBuilderProps.filters"
            :search="queryBuilderProps.search"
            :columns="queryBuilderProps.columns"
            :on-update="setQueryBuilder"
            :meta="users"
        >
            <template #head>
                <tr>
                    <th @click.prevent="sortBy('name')">Name</th>
                    <th v-show="showColumn('email')" @click.prevent="sortBy('email')">Email</th>
                </tr>
            </template>

            <template #body>
                <tr v-for="user in users.data" :key="user.id">
                    <td>{{ user.name }}</td>
                    <td v-show="showColumn('email')">{{ user.email }}</td>
                </tr>
            </template>
        </Table>
    </admin-layout>
</template>

<script>
import { InteractsWithQueryBuilder, Tailwind2 } from '@protonemedia/inertiajs-tables-laravel-query-builder';
import AdminLayout from '@/Pages/Admin/AdminLayout'

export default {
    mixins: [InteractsWithQueryBuilder],

    components: {
        Table: Tailwind2.Table,
        AdminLayout,
    },

    props: {
        users: Object
    }
};
</script>
DimaVIII commented 2 years ago

It's a feature of Query builder. You can add commas to preform filter search. The Demo script is bugged therefore. Quick fix is just to implode the array back to a string if you don't need multiple search filters.

        $globalSearch = AllowedFilter::callback('global', function ($query, $value) {
            $value = is_array($value) ? implode(",", $value) : $value;

            $query
                ->where('name', 'LIKE', "%{$value}%")
                ->orWhere('id', 'LIKE', "%{$value}%")
                ->orWhere('tags', 'LIKE', "%{$value}%")
                ->orWhereHas('comments', fn($query) =>
                    $query->where('body', 'like', '%' . $value . '%') )
                ->orWhereHas('firiend', fn($query) =>
                    $query->where('name', 'like', '%' . $value . '%'))
            ;
});