Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

hcastillo's avatar

How preservate parameters in pagination Laravel 10 + Inertia + vue 3

Hi, i having problem to preserve parameters from my pagination. i have 3 filters (isActive, isAuthorized, search) when u set any o them a watch from vue make a call to get the filtered data and everything is ok but went y try to search in next page all my parameters gone. in the pagination component i dont get the filters because i want to use current parameters from uri but cant

Index.vue

<script setup>
import Admin from "../../../Layouts/Coordinator.vue";
import MainTitle from "../../../Components/Common/MainTitle.vue";
import Pagination from "../../../Components/Common/Pagination.vue";
import { Link, router } from "@inertiajs/vue3";
import { ref, watch } from "vue";

const props = defineProps({
    filters: Object,
    users: Object,
});

const form = ref({
    perPage: props.filters.perPage,
    search: props.filters.search,
    isActive: props.filters.isActive,
    isAuthorized: props.filters.isAuthorized,
});

watch(form, (newForm) => {
    router.visit(route("usuarios.index", newForm));
});
</script>

<template>
    <Admin>
        <MainTitle title="Administración" />

        <div class="card mr-4">
            <header class="card-header">
                <p class="card-header-title">Usuarios</p>
            </header>

            <div class="card-content">
                <div class="content">
                    <div class="is-flex is-justify-content-space-between">
                        <div class="columns">
                            <div class="field is-horizontal">
                                <div class="field-label is-small">
                                    <label class="label">Usuario</label>
                                </div>

                                <input
                                    class="input"
                                    type="text"
                                    placeholder="Nombre"
                                    v-model="form.search"
                                />
                            </div>

                            <div class="field is-horizontal ml-3">
                                <div class="field-label is-small">
                                    <label class="label">Activo</label>
                                </div>

                                <div class="select">
                                    <select
                                        v-model="form.isActive"
                                        :key="`select-${form.isActive}`"
                                    >
                                        <option value="all">Todos</option>
                                        <option value="true">Si</option>
                                        <option value="false">No</option>
                                    </select>
                                </div>
                            </div>

                            <div class="field is-horizontal ml-3">
                                <div class="field-label is-small">
                                    <label class="label">Autorizado</label>
                                </div>
                                <div class="field-body">
                                    <div class="field is-narrow">
                                        <div class="select">
                                            <select
                                                v-model="form.isAuthorized"
                                                :key="`select-${form.isAuthorized}`"
                                            >
                                                <option value="all">
                                                    Todos
                                                </option>
                                                <option value="true">Si</option>
                                                <option value="false">
                                                    No
                                                </option>
                                            </select>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="columns">
                            <small class="mt-3">
                                <strong>Cant. por pagina</strong>
                            </small>

                            <div class="select ml-2">
                                <select
                                    v-model="form.perPage"
                                    :key="`select-${form.perPage}`"
                                >
                                    <option value="10">10</option>
                                    <option value="20">20</option>
                                    <option value="50">50</option>
                                </select>
                            </div>
                        </div>
                    </div>
                    <table
                        v-if="users.data.length >= 0"
                        class="table is-fullwidth"
                    >
                        <thead>
                            <tr>
                                <th>Nombre</th>
                                <th>Apellidos</th>
                                <th>Identificación</th>
                                <th>Email</th>
                                <th>Cargo</th>
                                <th>Activo</th>
                                <th>Autorizado</th>
                                <th>Acciones</th>
                            </tr>
                        </thead>
                        <tbody>
                            <tr v-for="user in users.data" :key="user.id">
                                <th>{{ user.name }}</th>
                                <td>{{ user.lastname }}</td>
                                <td>{{ user.identification }}</td>
                                <td>{{ user.email }}</td>
                                <td>{{ user.charge }}</td>
                                <td>
                                    {{ user.is_active === 1 ? "Si" : "No" }}
                                </td>
                                <td>
                                    {{ user.is_authorized === 1 ? "Si" : "No" }}
                                </td>

                                <td>
                                    <div class="is-flex">
                                        <Link
                                            :href="
                                                route('usuarios.edit', user.id)
                                            "
                                            class="button mr-3 is-warning is-small"
                                        >
                                            <span class="icon is-small">
                                                <i
                                                    class="pi pi-user-edit"
                                                    style="font-size: 1rem"
                                                ></i>
                                            </span>
                                        </Link>
                                        <button
                                            class="button is-danger is-small"
                                        >
                                            <span class="icon is-small">
                                                <i
                                                    class="pi pi-delete-left"
                                                    style="font-size: 1rem"
                                                />
                                            </span>
                                        </button>
                                    </div>
                                </td>
                            </tr>
                        </tbody>
                    </table>

                    <div v-if="users.data.length === 0" class="notification">
                        No hay usuarios disponibles con el
                        <strong>filtro</strong> que se tiene actualmente.
                    </div>

                    <Pagination :pagination="users.meta" />
                </div>
            </div>
        </div>
    </Admin>
</template>

Pagination.vue

<script setup>
import { Link } from "@inertiajs/vue3";

const props = defineProps({
    pagination: Object,
});
</script>

<template>
    <div class="m-2">
        <nav
            class="pagination is-centered"
            role="navigation"
            aria-label="pagination"
        >
            <ul class="pagination-list">
                <template v-for="link in pagination.links" :key="link.label">
                    <li v-if="link.label === '...'" :key="link.label">
                        <span class="pagination-ellipsis">&hellip;</span>
                    </li>
                    <li v-else :key="link.label">
                        <Link
                            preserve-scroll
                            preserve-state
                            class="pagination-link"
                            :aria-label="'Goto page ' + link.label"
                            :class="{
                                'is-current': link.active,
                                'has-text-grey-light': !link.url,
                            }"
                            :aria-current="link.active ? 'page' : null"
                            :href="link.url || null"
                            v-html="link.label"
                        />
                    </li>
                </template>
            </ul>
        </nav>
    </div>
</template>

Laravel controller method

    public function index(Request $request): Response
    {
        $perPage = $request->input('perPage', 10); // Get perPage query parameter, default to 10
        $search = $request->input('search', ''); // Get search query parameter
        $isActive = $request->input('isActive', 'all'); // Get isActive query parameter
        $isAuthorized = $request->input('isAuthorized', 'all'); // Get isAuthorized query parameter

        $query = User::query();

        if ($isActive !== 'all') {
            $query->where('is_active', '=', $isActive == 'true' ? 1 : 0);
        }

        if ($isAuthorized !== 'all') {
            $query->where('is_authorized', '=', $isAuthorized == 'true' ? 1 : 0);
        }

        if ($search) {
            // Add search conditions for each column you want to search in
            $query->where(function ($query) use ($search) {
                $query->whereRaw('LOWER(name) LIKE ?', ['%'.strtolower($search).'%'])
                    ->orWhereRaw('LOWER(lastname) LIKE ?', ['%'.strtolower($search).'%']);
            });
        }

        $users = UserResource::collection($query->oldest()->paginate($perPage));

        return Inertia::render('Coordinator/Users/Index', [
            "filters" => [
                'search' => $search, // Pass the search query to the view
                'perPage' => $perPage, // Pass the perPage value to the view
                'isActive' => $isActive,
                'isAuthorized' => $isAuthorized,
            ],
            'users' => $users,
        ]);
    }
0 likes
2 replies
LaryAI's avatar
Level 58

To preserve the parameters in pagination in Laravel 10 + Inertia + Vue 3, you can make use of the preserveState attribute in the Link component of Inertia. This attribute allows you to preserve the state of the current page when navigating to the next page.

In your Pagination.vue component, update the Link component as follows:

<Link
    preserve-scroll
    preserve-state
    class="pagination-link"
    :aria-label="'Goto page ' + link.label"
    :class="{
        'is-current': link.active,
        'has-text-grey-light': !link.url,
    }"
    :href="link.url || null"
    v-html="link.label"
/>

By adding the preserve-state attribute, the current state of the page, including the query parameters, will be preserved when navigating to the next page.

Additionally, make sure that your Laravel controller method is correctly retrieving the query parameters from the request and applying them to the query. The provided code snippet seems to be handling this correctly.

Remember to update your Laravel routes to use the preserve method when defining the route for the index action. This will ensure that the query parameters are preserved when navigating between pages.

Route::get('/users', [UserController::class, 'index'])->name('usuarios.index')->preserve();

With these changes, the query parameters for filters (isActive, isAuthorized, search) will be preserved when navigating to the next page in your pagination.

ThiagoDOM's avatar

Just add "->withQueryString()" after "paginate()" in your controller. Example:

    return Inertia::render('Admin/Users/List', [
        'users' => UserResource::collection(
            $user->latest()->paginate()->withQueryString()
        ),
    ]);
8 likes

Please or to participate in this conversation.