Laravel Inertia Course - Create a Custom Pagination Component
In Inertia, we don't have a pagination component to use; so, we have to create one.
From the paginated list, we have the links section where all the links for pagination are found in an array:
So, we iterate them:
<Link v-for="l in categories.links" :key="l" v-if="!l.active" class="px-2 py-1" :href="l.url" v-html="l.label"/>
To disable the current page and avoid leaving a link that navigates to itself, we can make a conditional and place a SPAN when the current page is used:
<template v-for="l in categories.links" :key="l">
<Link v-if="!l.active" class="px-2 py-1" :href="l.url" v-html="l.label"/>
<span v-else class="px-2 py-1" v-html="l.label" />
</template>
And add some styling to indicate that it is a disabled link, even though it is really a SPAN tag:
<template v-for="l in categories.links" :key="l">
<Link v-if="!l.active" class="px-2 py-1" :href="l.url" v-html="l.label"/>
<span v-else class="px-2 py-1 cursor-pointer text-gray-500" v-html="l.label" />
</template>
<script>
From Vue, we have a tag called "Component" with which we can dynamically render components based on a condition evaluated with the is prop:
import Foo from './Foo.vue'
import Bar from './Bar.vue'
export default {
components: { Foo, Bar },
data() {
return {
view: 'Foo'
}
}
}
</script>
<template>
<component :is="view" />
</template>
With this component in Vue, we can render either Vue or HTML components directly from the component definition:
<Component v-for="l in categories.links" :key="l" :is="!l.active ? 'Link' :'span'" class="px-2 py-1" :class="!l.active ? '' : 'text-gray-500 cursor-pointer'" :href="l.url" v-html="l.label" />
And with this, we have the same result as before, but the syntax is cleaner.
Now, in order to be able to reuse the component globally, we create a new component that receives the paginated list as a parameter using a prop:
resources/js/Shared/Pagination.vue
<template>
<!-- <Link class="px-2 py-1" v-if="!l.active" :href="l.url">{{ l.label }}</Link>
<span class="px-2 py-1 cursor-pointer text-gray-500" v-else>{{ l.label }}</span> -->
<template v-for="l in links" v-bind:key="l">
<Component v-html="`${l.label}`" class="px-2 py-1" :is="!l.active ? 'Link' : 'span'"
:href="l.url == null ? '#' : l.url" :class="!l.active ? '' : 'cursor-pointer text-gray-500'"
/>
</template>
</template>
<script>
import { Link } from '@inertiajs/vue3';
export default {
components: {
Link
},
props: {
links: Array
}
}
</script>
From the category list, we use this component:
resources/js/Pages/Dashboard/Category/Index.vue
***
<pagination :links="categories.links" />
</app-layout>
</template>
***
import Pagination from '@/Shared/Pagination.vue'
export default {
components:{
AppLayout,
Link,
Pagination
},
// ***
And we will get:
http://localhost/category?page=1
Video Transcript
Unfortunately in Laravel inertia we do not have a pagination component, so we have to implement one ourselves. The good thing is that it is very easy and we can then reuse it on any other page that we are going to use pagination, so let's go there. I am going to explain the code a little so that it is a little clearer for you. Here you can see the steps. Well, we have already gone through all this. What are we going to do? The pagination component, as you can imagine, is going to be a link. The pagination here is exactly the same as we have in Laravel, we have a parameter called page in the URL that indicates the page that we are going to display. So for that, here we are going to use the link and not the link, that is, the one labeled as mentioned before so that it is a spa-type pagination without reloading the entire page but the essential component. Well, then what we would do is place a dry link and that's it, based on the pagination that we already have, that is, we iterate the links, we draw them and it's over. Now here we can optimize it a little more, for example, asking if it is the active page then it places a spam. so that it can't navigate itself which is what happens in the actual pagination component of arabel So we can simulate it like this and from here we do some more optimizations but we're going to go little by little so we're going to come back here and the first thing we're going to do is create a separate folder or a separate file for such a resource since again we're going to want to reuse this in any other part of our application so.
Create the .vue component file
Here inside js very important I'm going to create one called share can be helper. So a bit of the same as always here you would place the html part and here would be the part of the Script block the first thing would be to import the necessary elements that would be in this case the link the same link that we used before here we have autocomplete and here would be components and we load our link to be able to use it within the page what else are we going to need the links that we are going to draw that is to say the pagination part which is an object just as we saw before that is to say we are going to want exactly this part that I showed you here All this the links is what we are passing it that I think is an object and right now in the same way we check it and that obviously we pass it through a prop since Remember that the props are the mechanism that we have to pass data between components in this case this component needs the links to be able to function or to be able to do its job So here we have everything necessary we are going to upload here we can in Vue 3 we can place multiple root components. that here the tab if you have it here the Index component we look for prop here and links here well it says it is a Ray right now I change it to see and here how the structure is look it is links here we have the data would be links then our prop is called links I am going to supply it with at least the complete component then it would be to place links here:
<script>
import { Link } from '@inertiajs/vue3';
export default {
components: {
Link
},
props: {
links: Array
}
}
</script>
For when we do not want to render any HTML, that is, we could have placed a div there but it would have been rendered every time we used v-for:
<template>
<Link class="px-2 py-1" v-if="!l.active" :href="l.url">{{ l.label }}</Link>
<span class="px-2 py-1 cursor-pointer text-gray-500" v-else>{{ l.label }}</span>
<template v-for="l in links" v-bind:key="l">
</template>
It is the parameter and since we want it to evaluate the condition, we put two points and we put the parameter here, it would be categories categories dot links, that would be the page that we have to pass the link to according to what was evaluated…
<Link class="px-2 py-1" v-if="!l.active" :href="l.url">{{ l.label }}</Link>
<span class="px-2 py-1 cursor-pointer text-gray-500" v-else>{{ l.label }}</span>
Then we escape the html but we will see it later so that it prints the character, here we have practically everything then we can navigate here you can see that I can go to the second page I have only three records, so it only navigates to them there is no longer a next this automatically if we check what is here in next in the href we have nothing…
So there you can put a condition that if URL is null you do something for example what do we want to do to avoid navigating to the same page which right now we can For example right now I am on page one here you can see one and two and I can click on one here and you can see that it is still navigating which although it does not happen much I do not want to do it like this I want the development to be a little nicer so for this here yes we can put a conditional was where I got a little bit married and here we ask if it is the active page which is another or another object that we have there another value Active if this we are going to print it if it is not active if it is active then we put a spam here I put the label:
<Link class="px-2 py-1" v-if="!l.active" :href="l.url">{{ l.label }}</Link>
<span class="px-2 py-1 cursor-pointer text-gray-500" v-else>{{ l.label }}</span>
The rest of the changes made are Tailwind classes to specify the hand using the cursor-pointer class, which simulates the cursor or the hand, and classes like a text color so it doesn't look so ugly; you can customize the style, add a border, background color, etc. The style, as always, depends on you, on how you want to define it.
Second format, using Component
Another component that in this case is the component called link, that is to say, here you can indicate how the hell you want this to be processed based on the attribute here called If which is the one that indicates what it is going to do if a spam again or that luckily they have the same behavior of passing the href and obviously the classes that are common in any component or html so that is basically what it does and here I was giving a small example of this in which I had a component called Fod a component called Bar and here it indicates based on some condition which in this case is Vue through the text:
import Foo from './Foo.vue'
import Bar from './Bar.vue'
export default {
components: { Foo, Bar },
data() {
return {
view: 'Foo'
}
}
}
</script>
<template>
<component :is="view" />
</template>
Note that it is a text that indicates the name of the component, what is going to be rendered, if this is true, that would be the good one, sorry, here I am not putting anything true, if we simply pass Fu here, then this is going to be rendered by the component called Foo, which can be anything, and if we put bar, it will be the component called bar, in the same way, we will see it, so we go there, we return here and I am going to duplicate this, I am going to comment on it here.
We are going to place the so-called component, I am going to close local here, and here we have to define the so-called is, what do we want it to evaluate, what is it going to place here, as I was telling you, we are going to place a condition, basically the value that we want to evaluate, so here we can also place a short conditional that indicates if active is defined, it means that we have to place a link, or in this case the opposite, if active is not defined, then we have to place the active point, it would be the link:
<Component v-html="`${l.label}`" class="px-2 py-1" :is="!l.active ? 'Link' : 'span'"
:href="l.url == null ? '#' : l.url" :class="!l.active ? '' : 'cursor-pointer text-gray-500'"
/>
And if it is active, that is to say, it is the page that we are viewing. It is the same, for example, page one, we have to place the spam, so here we place the html element called spam, here I place the two points and this would be all here. At this point, we would have to start cutting this, which is common here, for example, the URL, we can place it here in the span without any problem and here, this would no longer be necessary. So we can discard it, these classes that are common would remain, so we can place them here too; Remember that we are indicating these two classes here and there are two classes that are not common, so here we can also evaluate an additional class but in this case we put two points since we want to evaluate it. Remember that all of this is View code and here we can also ask if it is if it is not active then we put something and if it is and if it is active we put something else then basically the same condition that we have up there if it is if it is not active that is to say it would be for example my example I am on page one it would be page two so there you can place specific classes that in my case I do not need So I am going to directly place an empty one and if it is the page that is active in my case it would be page one I place these classes which is the same as we have here and well the result should be exactly the same as we have I am going to Well I am going to lower this here a little bit and there you can see it then we save we return here and here we have an error well This is new this had not happened to me in the previous version of the course but I think it does not want the href to be null and we gave it null so it places it like this and here that is to say here I evaluate if this is null then I print this character for example and if not I print this here I also missed one more thing which would be the V html to print the Label then here we put the dot Label and this would be it Practically everything it seems to me I'm going to put it up here to see what problem it has here it is here you can see that it works correctly and you can evaluate well we should remove this so that it is not printing this up here correctly here you have it has the link.
Remember that al is translated as a link and has spam Although if you don't like it it's okay you can also leave this format but it was to show you another possible implementation so well with this we finish this class
- Andrés Cruz
Develop with Laravel, Django, Flask, CodeIgniter, HTML5, CSS3, MySQL, JavaScript, Vue, Android, iOS, Flutter