Inertia mounted hook with search resets pagination on every action

Viewed 574

My vue file:

data() {
    return {
        search: '',
    }
},
mounted() {
    this.search = this.filters.search ?? '';
},
watch: {
    search(value) {
        Inertia.get('/contacts', { search: value }, {
        preserveState: true,
        replace: true,
    })
}

The Laravel Controller:

$contacts = Model::query()
             ->paginate(10)
             ->withQueryString();

return Inertia::render('Contacts/List', [
    'contacts'    => $contacts,
    'filters'     => request()->only(['search']),
    'currentPage' => request()->page,
]);

It all works perfectly if the mounted block is missing. With it, on every Inertia reload a "new search" is registered (since it's changed in the mounted hook) and it returns to page 1, so basically, every time you change the page it returns you to page 1.

It should be working perfectly with the Composition API's setup, but not sure why can't I get it to work here.

2 Answers

I use axios instead of Inertia.js in pagination

         <template>
        <div class="row mt-4">
            <div class="col-md-5">
                <span
                    >showing {{ data.from }}-{{ data.to }} of
                    {{ data.total }} items</span
                >
            </div>
            <div class="col-lg-7">
                <nav aria-label="...">
                    <ul class="pagination float-end">
                        <template v-for="link in data.links" :key="link.id">
                            <li v-if="!link.url" class="page-item">
                                <a @click.prevent="paginate(link.label)" class="page-link">
                                    <span
                                        aria-hidden="true"
                                        v-html="link.label"
                                    ></span>
                                </a>
                            </li>
                            <li
                                v-else
                                :class="{ active: link.active }"
                                class="page-item"
                            >
                                <a
                                    @click.prevent="paginate(link.label)"
                                    v-html="link.label"
                                    class="page-link"
                                ></a>
                            </li>
                        </template>
                    </ul>
                </nav>
            </div>
        </div>
    </template>

    <script>
    import axios from 'axios'
    export default {
        props: ["data", "url"],
        methods: {
            paginate(label) {
                console.log(`${route(this.url)}?page=${label}`);
                axios.get(`${route(this.url)}?page=${label}`).then((res) => {
                    this.$emit('paginate', res.data)
                });
            }
        }
    }
    </script>

I ran into the same issue, and after some digging I found this answer. The gist is that you should set your search parameter directly in the data attribute instead of using mounted():

data() {
    return {
        search: this.filters.search ?? '',
    }
},
watch: {
    search(value) {
        Inertia.get('/contacts', { search: value }, {
        preserveState: true,
        replace: true,
    })
}
Related