1

I'm trying to implement a pagination with Laravel 9 and Vue 3. But it's my first time that I'm doing this, and I don't know what to do.

First, I imported my library:

import { Link }  from '@inertiajs/inertia-vue3';

Second, I have my component pagination in components folder.

<script setup>
import { Link }  from '@inertiajs/inertia-vue3';

defineProps({
    data: {
        type: Object,
        default: () => ({}),
    },
});
</script>


<template>
    <div v-if="data.links.length > 3" class="flex justify-center mt-4 space-x-4">
        <Link
            v-for="(link, k) in data.links"
            :key="k"
            class="px-4 py-3 text-sm leading-4
            bg-white rounded hover:bg-white
            focus:text-indigo-500 hover:shadow"
            :class="{'bg-indigo-400 text-white': link.active}"
            :href="link.url"
            v-html="link.label"
        />
    </div>
</template>

Third, I imported my component into my other component:

    <!-- ... -->
    </table>
    <pagination :data="preContracts" />
</template>

<script>
import usePrecontract from "../composables/precontract"
import { onMounted, defineComponent } from 'vue'
import pagination from "../components/pagination"
import { Head } from "@inertiajs/inertia-vue3";
import { Link } from "@inertiajs/inertia-vue3";
import { Inertia } from "@inertiajs/inertia";


export default defineComponent({
    name: 'datatablePreContracts',
    setup() {
        const { preContracts, getPrecontract, deletePrecontract, queryForKeywords } = usePrecontract()

        onMounted(getPrecontract)

        function remove(id) {
            deletePrecontract(id)
        }

        function searchId(action) {
            let id = document.getElementsByClassName('id_search')[0].value
            const params = [action, id];

            queryForKeywords(params)
        }

        function searchName(action) {
            let id = document.getElementsByClassName('name_search')[0].value
            const params = [action, id];

            queryForKeywords(params)
        }

        function searchPhone(action) {
            let id = document.getElementsByClassName('phone_search')[0].value
            const params = [action, id];

            queryForKeywords(params)
        }

        function contract(action) {
            alert("llego contract -> " + action);
        }

        function edit(action) {
            alert("llego edit -> " + action);
        }

        function show(action) {
            alert("llego show -> " + action);
        }

        function installation(action) {
            alert("llego installation -> " + action);
        }

        return {
            preContracts,
            remove,
            searchId,
            searchName,
            searchPhone,
            contract,
            edit,
            show,
            installation
        }
    }
})
</script>

In app.js, I have this:

import pagination from './components/pagination';

const app = createApp({
    components: {
        datatableUsers,
        datatableRoles,
        datatablePermissions,
        datatablePrecontract,
        pagination
    }
}).mount('#app')

But when my page is loaded, I have this in console:

Failed to resolve component: pagination If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement. at

I don't know what I'm doing wrong. Can anyone help me?

UPDATE

With the help of @Angelina I resolved my problem in web browser console.

In app.js I change this:

const app = createApp({
    components: {
        datatableUsers,
        datatableRoles,
        datatablePermissions,
        datatablePrecontract,
    }
})
app.component('pagination', pagination);
app.mount('#app')

Then I mount my component:

<pagination :data="preContracts.links" />

But now my pagination isn't shown.

UPDATE 2

This is my data in console:

{,…}
data: [{id: 10000, id_date: 0, id_commercial: 35, numerical_serie: 0, co_owner: 0, simplify: 0,…},…]
links: {first: "http://www.crm.local:8081/api/preContractApi?page=1",…}
meta: {current_page: 1, from: 1, last_page: 100,…}

Thanks for the help, and sorry for my bad English.

scorpions78
  • 553
  • 4
  • 17
  • Can you `console.log()` the data you pass to the pagination component and update the question? –  Feb 22 '23 at 16:11
  • @Angelina i update my question with console.log – scorpions78 Feb 23 '23 at 07:22
  • The problem is that `links` (`links: {first: "http://www.crm.local:8081/api/preContractApi?page=1",…}`) is an object, not an array, and objects don't have `.length` property, so `v-if="data.links.length > 3"` condition isn't met. –  Feb 23 '23 at 11:19
  • @Angelina y remove if. same problem – scorpions78 Feb 23 '23 at 11:33
  • Can you create a repo of your project on GitHub and link it to me, so I can clone it and reproduce your problem? Because it isn't obvious to me already. Plus, honestly, I've never used Inertia, sorry. Well, this is a good chance to start, I guess. –  Feb 23 '23 at 16:01
  • @Angelina thaks for your comment and your help. i response to myself in this post with my solution. – scorpions78 Feb 24 '23 at 08:44

3 Answers3

1

Here you might find the answer.

Registering components in the root component's components option doesn't make them global. Doing that just makes them available to the root component itself, not its children.

To register components globally, use app.component in your top-level code.

app.js

import { createApp } from 'vue';
import App from './App.vue';
import MyGlobalComponent from './components/MyGlobalComponent.vue';
const app = createApp(App);
app.component('MyGlobalComponent', MyGlobalComponent); ✅
const mountedApp = app.mount('#app');
  • thanks for your response. but if you show my question i wrote my pagination component into my definition components App. I imported it and i added in component CreateApp – scorpions78 Feb 22 '23 at 11:53
  • @scorpions78, well, maybe pagination component is not resolved in another non-root component. Anyway, if you want to make the component global, you will have to use `app.component()`, because registering components like you did makes them available only to the root component itself, not its children. –  Feb 22 '23 at 12:29
  • ok, i understood. Now my problem it´s that i don´t show pagination. now it´s ok, in console don´t show error, but in inspector not show pagination. Update my question – scorpions78 Feb 22 '23 at 12:41
0

You have a ready solution for this, why are you trying to reinvent the wheel? Installation is really simple and well documented.

  • thanks for your comment but i´m learning how to do this. Now I´m reading this documentation and traying this examples... but now in my console i don´t show any problem or error, but i can´t show my pagination... – scorpions78 Feb 22 '23 at 15:44
0

Sorry for this answer, but I believe that I found my problem... I have this in my controller:

return PreContractResource::collection(PreContract::with(['personalData','statusPre'])->paginate(10));

This returns a collection that contains all information from contracts and my pagination links.

But when I build my Axios petition, this is returned:

{,…}
data: [{id: 10000, id_date: 0, id_commercial: 35, numerical_serie: 0, co_owner: 0, simplify: 0,…},…]
links: {first: "http://www.crm.local:8081/api/preContractApi?page=1",…}
meta: {current_page: 1, from: 1, last_page: 100,…}

But when I try to access links, this is displayed in the console:

app.js:7203 [Vue warn]: Failed to resolve component: inertia-link If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.

at <Pagination class="mt-6" links=undefined >

at <DatatablePreContracts>

at <App>

When I console.log preContract.links, undefined is returned.

But in my petition it's... I don't know what I'm doing wrong. My table is filled perfectly with this pattern:

<template v-for="item of preContracts">
    <tr>
        <td>{{ item.id }}</td>
        <td>{{ (item.personal_data) ? item.personal_data.name : '' }} {{ (item.personal_data) ? item.personal_data.surname1 : '' }} {{ (item.personal_data) ? item.personal_data.surname2 : '' }}</td>
        <td>{{ (item.personal_data) ? item.personal_data.address : ''}}, {{ (item.personal_data) ? item.personal_data.population : ''}}</td>
        <td>{{ (item.personal_data) ? item.personal_data.landline : ''}} </td>
        <td>
            <span class="text-light" :class="item.status_pre.class_span">
                {{ (item) ? item.status_pre.name : 'null' }}
            </span>
        </td>

And all my data is ok...

My problem is that, for a strange reason, I can't get access to links...

UPDATE

I resolved my problem thanks to this thread.

Finally, I imported the pagination component into app.js to construct the global pagination.

app.component('pagination', require('./components/Pagination.vue').default);

Then I changed the pagination in my data table:

<pagination :pagination="pagination" :offset="7" @paginate="getPage(this.pagination.current_page)"></pagination>

I created a function in my script.

First, to do this, I added my composable function to my constant name:

const { preContracts, getPrecontract, deletePrecontract, queryForKeywords, getResults, **getItems** } = usePrecontract()

... and created function getPage(item):

function getPage(page){
    getItems(page);
}

... and wrote this in my composable:

export default function usePrecontract() {
    let preContracts = ref([])
    let pagination = ref([])

    const getPrecontract = async () => {
        let response = await axios.get('/api/preContractApi')
        preContracts.value = response.data.data
    }
    const deletePrecontract = (id) => axios.post(`/api/preContractApi/${id}`, {_method: 'delete'}).then(res => {
        confirm("Are you sure you want to delete this item?")
        location.reload();
    }).catch(err => {
        console.log(err);
    });

    const queryForKeywords = async (event) => {
        const response = await axios.get('/api/preContractApi/show', {params: {'searchParams': event}})
        preContracts.value = response.data.data
    };

    const getResults = async (page) => {
        const response = axios.get('api/preContractApi?page=' + page)
        preContracts.value = response.data
    };

    const getItems = async (page) => {
        axios.get('/api/preContractApi?page=' + page)
            .then(response => {
                preContracts.value = response.data.data;
                pagination.value = response.data.meta;
            });
    };

    return {
        preContracts,
        getPrecontract,
        deletePrecontract,
        queryForKeywords,
        getResults,
        getItems
    }
}

Thanks everyone in this thread for the help and @SAKIB for his response in another thread that helped me!

scorpions78
  • 553
  • 4
  • 17