Earlier this week I was talking to a good friend of mine (who is also a recent convert to the School of Vue) and he was talking about the troubles he went through in adding table sorting and pagination to a table. He was making use of a particular Vue component that was - to be nice - "undocumented". While I was reasonable certain that other solutions existed, I thought it would be fun to take a stab at writing my own support for table sorting and pagination. Not a generic solution, but just a solution for a particular set of data.
I began with a Vue app that loaded in data via an Ajax call and rendered a table. This initial version has no sorting or pagination, it just loads data and dumps it in the view. Here's the layout:
<div id="app">
<table>
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Breed</th>
<th>Gender</th>
</tr>
</thead>
<tbody>
<tr v-for="cat in cats">
<td>{{cat.name}}</td>
<td>{{cat.age}}</td>
<td>{{cat.breed}}</td>
<td>{{cat.gender}}</td>
</tr>
</tbody>
</table>
</div>
I've got a table with four columns: Name, Age, Breed, and Gender. And then I simply loop over my cats to render each row. The JavaScript is simple:
const app = new Vue({
el:'#app',
data:{
cats:[]
},
created:function() {
fetch('https://www.raymondcamden.com/.netlify/functions/get-cats')
.then(res => res.json())
.then(res => {
this.cats = res;
})
}
})
(As an aside, I say it's simple, but as always, if anything here doesn't make sense, just ask me in the comments below!) While it isn't too exciting, you can see this running below.
See the Pen Vue - Sortable Table by Raymond Camden (@cfjedimaster) on CodePen.
Alright, so for the first update, I decided to add sorting. I made two changes to the view. First, I added click handlers to my headers so I could do sorting. Secondly, I switched my loop to use sortedCats
, which I'm going to set up as a Vue computed property. Here's the new HTML:
<div id="app">
<table>
<thead>
<tr>
<th @click="sort('name')">Name</th>
<th @click="sort('age')">Age</th>
<th @click="sort('breed')">Breed</th>
<th @click="sort('gender')">Gender</th>
</tr>
</thead>
<tbody>
<tr v-for="cat in sortedCats">
<td>{{cat.name}}</td>
<td>{{cat.age}}</td>
<td>{{cat.breed}}</td>
<td>{{cat.gender}}</td>
</tr>
</tbody>
</table>
debug: sort={{currentSort}}, dir={{currentSortDir}}
</div>
On the JavaScript side, I had to do a few things. First, I added properties to keep track of what I was sorting by and in what direction:
data:{
cats:[],
currentSort:'name',
currentSortDir:'asc'
}
Next, I added the sort
method. It has to recognize when we are sorting by the same column and flip the direction:
methods:{
sort:function(s) {
//if s == current sort, reverse
if(s === this.currentSort) {
this.currentSortDir = this.currentSortDir==='asc'?'desc':'asc';
}
this.currentSort = s;
}
}
Finally, I added my computed property, sortedCats
:
computed:{
sortedCats:function() {
return this.cats.sort((a,b) => {
let modifier = 1;
if(this.currentSortDir === 'desc') modifier = -1;
if(a[this.currentSort] < b[this.currentSort]) return -1 * modifier;
if(a[this.currentSort] > b[this.currentSort]) return 1 * modifier;
return 0;
});
}
}
I'm just using the sort
method of my array with the property being dynamic. The modifier
bit just handles reversing the numbers based on the direction of the sort. You can test this version below:
See the Pen Vue - Sortable Table (2) by Raymond Camden (@cfjedimaster) on CodePen.
By the way, you'll notice some debug data at the bottom of the view. In a real application I'd remove that, but I used that as a handy way to track values while I was clicking. I could have used Vue DevTools for that, although I'm not certain how well they work with CodePens.
Woot! Almost there! For the final version I added pagination. I didn't want to add more cats to my JSON data set, so I used a relatively small "page size" of 3. I began by adding buttons to the front end for pagination:
<p>
<button @click="prevPage">Previous</button>
<button @click="nextPage">Next</button>
</p>
In the JavaScript I made the following changes. First, I added values to track the page size and current page:
data:{
cats:[],
currentSort:'name',
currentSortDir:'asc',
pageSize:3,
currentPage:1
},
Next, I added the prevPage
and nextPage
methods, which were pretty simple:
nextPage:function() {
if((this.currentPage*this.pageSize) < this.cats.length) this.currentPage++;
},
prevPage:function() {
if(this.currentPage > 1) this.currentPage--;
}
Finally, I modified my computed property to check the page size and current page values when returning data. I did this via a filter
call:
sortedCats:function() {
return this.cats.sort((a,b) => {
let modifier = 1;
if(this.currentSortDir === 'desc') modifier = -1;
if(a[this.currentSort] < b[this.currentSort]) return -1 * modifier;
if(a[this.currentSort] > b[this.currentSort]) return 1 * modifier;
return 0;
}).filter((row, index) => {
let start = (this.currentPage-1)*this.pageSize;
let end = this.currentPage*this.pageSize;
if(index >= start && index < end) return true;
});
}
Note the creation of a start
and end
value. I almost always screw this up so I created variables instead of a super complex if
statement. While my code seems to work I'm still not 100% sure that math is right. And here is that final version:
See the Pen Vue - Sortable Table (3) by Raymond Camden (@cfjedimaster) on CodePen.
So that's it. There is definitely room for improvement. I'd like to add disabled
to the buttons when they are at the 'edge' and I'd like to highlight, somehow, the table headers when sorting, but I'll leave that as an exercise to my readers. ;) (Don't forget you can fork my CodePens and add your own edits!)
Header Photo by Hannes Egler on Unsplash
Archived Comments
Thanks for this post Ray. How would your code change if this code appeared on a child component of App.vue? In using your example (Vue - Sortable Table 2), I'm getting the error "TypeError: this.cats is undefined" w/in the 'export default {)' section of the child component. I can't determine of this is a Vue lifecycle or prop/slot issue between App.vue and the child component or something else?
Do you have a CodePen for this?
I'm using Vuetify/Vue to display a bunch of pages that are simple 'vue snippets' of code as a reference/learning exercise. I wanted
to add a new snippet, based on this blog post. I've included my App.vue,
main.js and TableSort.vue in one gist.
https://gist.github.com/ano...
I'm not quite sure what is wrong. I haven't done much with "multi component" Vue apps yet so I'm still a bit unsure in that area. If you have a complete project I could clone and run I could take a stab at it.
See if this works. Will need to install dependencies. FTR, your 'Form Stepper' example is there as well. :) https://filetea.me/n3wSdH2p...
And I had no issues getting your code to work as a single standalone page.
Link doesn't seem to work.
Sorry. Timed out I guess. No worries.
Very informative
Are there any repositories on github to download the example?
No but you can download from the CodePen embeds.
Thank you Raymond for the quick response
One more question, can you change the source, instead the json to scrape the data from a remote table/page using xpath or something like this. I have seen recently you have done an scraping example in Firefox.
Sure you can change the source, but be aware that you would need to change the code too obviously. So my table, for example, is hard coded for the data.
You can download from codepen with export button.
hi raymond, thank you so much for this tutorial. I am new in vue js and I wondered how to put a search input on the top of the table.
by adding this line of codes solved my problem. thanks again raymond.
var self=this;
return this.categories.filter(function(ctg){return ctg.title.toLowerCase().indexOf(self.search.toLowerCase())>=0;});
Glad you got it!
excellent tutorial for anyone learning the basics. next would be adding a check box or button column!!
Can you clarify what you mean?
adding check box columns or button columns so that actions can be taken on a row. but all in all a very good tutorial.
there is one issue that i fixed this computed and that is that you have to make a copy of the array with .slice() function to make sure you're not modifying the original (sideeffect).
Ah in theory then thats just a table cell with @click="doSomething(cat)"
Excellent tutorial. I would like to show the prev and next buttons if and only if there are going to be prev and next elements. I tried the following code to hide the prev button on the first page but didn't quite work:
if(this.currentPage < 1) {this.showprev = 0} else {this.showprev = 1} and then in html v-if="showprev > 0"
I would like to do something similar to show the next page too
Here is the first version - but it has too much logic in the view. Going to fix that:
https://codepen.io/cfjedima...
And this version is nicer imo: https://codepen.io/cfjedima...
It worked. One more minor issue that I have found is that when I do numerical sorting, it doesn't sort by the amount. Instead it looks at the first number and sorts accordingly. For example, 2000 will appear after 200 even though 300 and 500 are on the list.
Good find. Give me 10.
So wait - in my demo, I can sort by age just fine. Do you see that?
Strange - May be because I I have decimals in my numbers. This is the logic I have for the sorted products.
sortedProds: function() {
return this.filteredProds.sort((a,b) => {
let modifier = 1;
if(this.currentSortDir === 'desc') modifier = -1;
if(a[this.currentSort] < b[this.currentSort]) return -1 * modifier;
if(a[this.currentSort] > b[this.currentSort]) return 1 * modifier;
return 0;
})
In theory it shouldn't matter - do you have your JSON data available online?
[
{
"id": 124,
"name": "iPhone X 256GB Silver",
"image": "",
"purchasedate": "2018-05-14T07:00:00.000Z",
"price": "124.00"
},
{
"id": 125,
"name": "Memorex - PurePlay Portable Speaker",
"image": "",
"purchasedate": "2018-05-14T07:00:00.000Z",
"price": "345.00"
}
Your prices aren't numbers - they are strings. Remove the quotes around them.
"price":99.99
Ok I will try that. I will probably have to do that on the client side somehow because they are coming from an api.
Ah. If so - iterate over the array and use parseFloat - https://developer.mozilla.o....
Great tutorial, was able to tie this logic into an existing Vue.js + Laravel app. Nice and elegant, thank you very much!
You should be aware that you can not have the sortedCats as a computed property if you plan to use this as a basis for a re-usable component, it will cause an infinite render loop, because the v-for loop will constantly update, because applying the sort causes an update then the update causes an update and so on and so on. You have to have the sortedCats computed property be a function in your methods and then add watch for the currentSort and currentSortDir that calls the sortedCats method.
watch: {
'currentSort': 'sortedCats',
'currentSortDir': 'sortedCats'
}
Interesting - can you explain why it works ok as a bare Vue app but not as a component?
I am by no means an expert, but I discovered when you have more than one instance of it as a reusable component it causes this side effect.
I loved your tutorial as it gave me the perfect starting point for my data table, I have added complete pagination, hide/show columns and filtering, then went to use it in my project and got the error.
It took me about 5 hours of searching on Google before I found the explanation i posted. It boils down to that when you click on the header to sort the column - that click event causes the component to re-render and then the computed property detects the change and also causes a re-render, and that re-render causes the computed property to re-render again and therefore the infinite loop.
By using a watcher to call the sort, it prevents the sort functionality from triggering a re-render.
I just wanted to save anyone who uses your tutorial the headache I ran into if they wanted to have multiple tables in a single vue instance.
Fascinating. Thank you for sharing this. I'm going to build a demo that replicates the issue and then show the fix. I'll do this in a blog post and then delete these comments so I can take credit and - oh wait - I'm typing this - what I mean is - I'll post a follow up and credit you! :)
Query - can you share your code? Im curious about how this bug is occuring. It sounds like the array is being passed by ref instead of by copy.
LOL!!! I plan to give you credit in my code, for your code that I used. I am developing a new Vue component library called Vui and the beta release will be launched soon, hope to have the official launch end of July. I'll let you know.
Feel free to drop me an email (if you don't mind) when you go live - I'd like to find time to review it on the blog.
Excellent will do!!!
How would this example work with null values intermixed in the dataset, if we want the null values to come at the end?
Fork the CodePen and try - then let us know. :)
Sorry should have been more specific haha - I have tried this and it messes up the sorting, not sure exactly why. It goes through a specific pattern (like 5 different type of sorts), maybe dependent on the # of null values? Not sure, was wondering if anyone else ran into this bug and whether they found a fix.
Actually just solved this. Just make sure to also do a check for typeof a[this.currentSort] == 'undefined') and b[this.currentSort] == 'undefined') during the sortedRows() function. Sort accordingly (put null values at either the end or beginning).
Sweet - thank you for sharing what worked!
how to add search on this table..?
It would be a few steps. First, add some UI to let you type, an input field. Then instead of using a data field (cats), you would use a computed property where the array is filtered by the search term.
Oops, I forgot I was already using a computed property - sortedCats. You would make *that* logic also do filtering. That may impact paging though.
So I worked up this - https://codepen.io/cfjedima.... But I feel like when you change the filter it should reset to page 1.
hey thanks man for yours help..i was asking because you already using a computed property .
You can add a watcher for that:
watch: {
search: function() {
this.currentPage = 1
}
},
Try forking my codepen with that. :)
Got a Code-Pen I can fork?
Err wait... this isn't my code at all. You are using a Vue plugin?
I have some problems with sorting...
This is sort by Price https://drive.google.com/op...
This is sort by ID https://drive.google.com/op...
This is sort by Name https://drive.google.com/op...
It is sorting numbers by first number 1, 10, 100, 2, 20, 200, 3... And letters by random as I can see.
Can You help me somehow? What can make this kind of problem?
Instead of sharing pics, please share a Code-Pen I can run and test.
https://codepen.io/bonitasr...
I had no Code-Pen so I needed to create it, hope it is ok because I use Code-Pen for the first time... I'm sorry I late.
I figured out what is problem... This plugin sort per ASCII kod and 4 > 1 and doesn't metter if one number is 4 and other is 19999, it compares only first character.
Can you help me with something like IF statement here:
computed:{
sortedProducts:function() {
return this.products.sort((a,b) => {
let modifier = 1;
if(this.currentSortDir === 'desc') modifier = -1;
if(a[this.currentSort] < b[this.currentSort]) return -1 * modifier;
if(a[this.currentSort] > b[this.currentSort]) return 1 * modifier;
return 0;});
}}
and combined with this:
function compareNumbers(a, b) {
return a - b;
}
Right, this is expected as the sort is going to assume you are sorting strings, not numbers. Is your price data properly set as number values and not strings? An easy way to do that would be when you load your data, loop over it and do something like: x = parseInt(x, 10);.
I had some other stuffs to do so I didn't work on this.
How can I check which <th> is clicked and if it's "name" then to use Your code and if it is number (id, price or pzn) to use parseFloat()...
I have problem with checking which fields is clicked. I'm pretty new with Vue.
Amazing how simple and clean this solution is! What about adding some css icons on the <th> to show the sorting direction?
Is your TH dynamic?
No, it is static and it won't be changed I think ever.
Modify the click event to pass in the name.
Wonderful tutorial. Shouldn't changing a[this.currentSort] to a[this.currentSort].toUpperCase() give me case insensitive sorting? I'm getting a Cannot read property 'toUpperCase' of undefined error...
It should work - can you setup a CodePen with this and share the URL?
Just wanted to say you are so totally badass man! I swear I was thinking about which component to go for but you simplified it like it was nothing! If it isnt too much to ask, could you kindly add a follow up post to this that also covers filtering, would be super awesome if you could do that
I just verified that my code is actually identical to yours except I changed "cats" to "games". But it currently sorts numbers, and I'm guessing toUpperCase will cause an issue if you pass it a number. Anyways, I'll throw up a CodePen if I can't figure it out. Thanks!
Thank you for the kind words (and if this helps, visit the Amazon Wishlist linked to above ;) - try this - I wrote it pretty quickly though:
https://codepen.io/cfjedima...
Hello, can u help me to make pagination like in this screenshot? I want to see all pages and click on page what I want. Now its only works to previous and next page
https://uploads.disquscdn.c...
It's possible - you would need to determine how many total pages you have first. I can help and I think it would be a good followup, but I may not get to it for a while - have a busy couple of weeks coming up.
Thoughts on this version? https://codepen.io/cfjedima...
Thank you for the amazing code! simple and working. I ran also in another problem: how can I sort by 2 columns? eg. Sort by country asc/desc and name asc? I extended your code and just appended 2 columns in the comparision. It works but when I sort country by desc, also names are sorted by desc. Any thoughts?
Honestly all I can suggest is what I'd do - Google for sorting JavaScript arrays by two criteria.
In theory you would do something like - if a == b (ie the first sort criteria matches) then you compare c and d- the second criteria.
i need this. thanks for the wonderfull article
Thanks this worked for me....
Thanks bro
Hi! This tutorial was easy to follow and greatly helped me learn some tricks for sorting a table in Vue. But I'm having the same problem with the infinite loop on a reusable component. Wondering if you ever got a demo working to replicate the issue. Thanks!
I don't know if this solution will work for everyone, but here's how I fixed the infinite loop problem in my setup:
I changed sortedCats from a computed property to a method, and I renamed it getSortedCats. I created a new variable in data called sortedCats, and set its default value = cats. Then instead of having my v-for loop over the computed property, I have it looping over the sortedCats variable. The last line of my sort() function now looks like this:
this.sortedCats = this.getSortedCats();
So sortedCats only changes when the sort() function is invoked. For me, this wound up satisfying my use case. It works faster than my previous method and didn't require writing a custom watcher. Again, this may not be a solution for everyone, but I hope it helps.
Thanks for sharing this, Jared!
Raymond,
This is great code for sorting a vue table. I wanted to add filtering per column. I already have the filter code working in my code, but could not figure out how to add sorting to it! I'm kind of a beginner at Vue ( though a few years in Javascript ). Any direction you could give me? Thanks, man.
You want filtering *per* column? Like you imagine one input field above each column to allow for filtering?
Raymond,
Thank you much for the
quick response!
I've already got Vue code to filter on more than one column.what I couldn't figure out was how then to sort the whole table by a column. Using Vue I can either filter or sort, but not both..
E.g. show me every record where building = 24, then sort the whole table by room
Ok, so have you tried adding in this code? If so, how did it fail?
Let me post the code I have...no time to do it this moment..
Raymond, here is my code so far for filtering per column. Some of your sorting code is there, but as I say I could not figure out how to add it to the same table.
My table uses filteredBlogs as the source array ( computed property). How can I
use sortedBlogs in addition?
Thanks for any insights...As I say I am near a beginner at Vue
[code - note this code is run in the Webpack local dev server..]
// filename = showBlogs.vue
//
<template>
<div id="show-blogs" v-on:keyup.enter="go()">
<h1>All Blogs</h1>
<input type="text" id="tsearch1" placeholder="lens"/>
<input type="text" id="tsearch2" placeholder="type"/>
<input type="text" id="tsearch3" placeholder="stn"/>
<input type="text" id="tsearch4" placeholder="c_start"/>
<input type="text" id="tsearch5" placeholder="destination"/>
<input type="text" id="tsearch6" placeholder="room"/>
<input type="text" id="tsearch7" placeholder="user"/>
<button v-on:click="go()">GO</button>
<div>
<table id="tdisplay">
<thead>
<tr>
<th @click="sort('lens')">LENS</th>
<th @click="sort('typ')">TYPE</th>
<th @click="sort('stn')">STN</th>
<th @click="sort('c_start')">C_START</th>
<th @click="sort('destination')">DESTINATION</th>
<th @click="sort('room')">ROOM</th>
<th @click="sort('user')">USER</th>
</tr>
</thead>
<tbody>
<tr v-for="blog in filteredBlogs">
<td>{{ blog.lens}}</td>
<td>{{ blog.typ }}</td>
<td>{{ blog.stn }}</td>
<td>{{ blog.c_start }}</td>
<td>{{ blog.destination }}</td>
<td>{{ blog.room }}</td>
<td>{{ blog.user }}</td>
</tr>
</tbody>
</table>
</div>
</div>
</template>
<script>
export default {
data () {
return {
blogs:[],
currentSort:'lens',
currentSortDir:'asc',
search1: '',
search2: '',
search3: '',
search4: '',
search5: '',
search6: '',
search7: ''
} // return
}, //data
methods:{
go: function(){
// alert("Go button was clicked");
this.search1 = tsearch1.value;
this.search2 = tsearch2.value;
this.search3 = tsearch3.value;
this.search4 = tsearch4.value;
this.search5 = tsearch5.value;
this.search6 = tsearch6.value;
this.search7 = tsearch7.value;
},
sort : function(s){
//if s == current sort, reverse
if(s === this.currentSort) {
this.currentSortDir = this.currentSortDir==='asc'?'desc':'asc';
} // end if
this.currentSort = s;
console.log(this.currentSort);
} // end sort
}, // end methods..
created(){
this.blogs = [
{
'lens': '000001',
'typ': 'S',
'stn': '1234',
'c_start': 'K2-123',
'destination': 'Verrill',
'room': '88',
'user' : 'phild'
},
{
'lens': '003004',
'typ': 'S',
'stn': '5678',
'c_start': 'K2-456',
'destination': '118',
'room': '127',
'user' : 'Ho, Janet'
},
{
'lens': '000034',
'typ': 'S',
'stn': '3434',
'c_start': 'SC-057',
'destination': 'Argiro',
'room': '88',
'user' : 'phild'
},
{
'lens': '003007',
'typ': 'S',
'stn': '209-1111',
'c_start': 'LB-066',
'destination': 'LBSW',
'room': '200',
'user' : 'Circulation Desk'
},
{
'lens': '002145',
'typ': 'S',
'stn': '469-6666',
'c_start': 'LB-123',
'destination': "Men's Peace Palace",
'room': '23',
'user' : 'MVVT Line'
},
{
'lens': '001145',
'typ': 'v',
'stn': '2346',
'c_start': '',
'destination': 'Verrill',
'room': '25',
'user' : 'Vacant Port'
}
]
},
computed: {
filteredBlogs: function(){
return this.blogs.filter( (blog) => {
return ( blog.lens.toLowerCase().match(this.search1.toLowerCase())
&& blog.typ.toLowerCase().match(this.search2.toLowerCase())
&& blog.stn.toLowerCase().match(this.search3.toLowerCase())
&& blog.c_start.toLowerCase().match(this.search4.toLowerCase())
&& blog.destination.toLowerCase().match(this.search5.toLowerCase())
&& blog.room.toLowerCase().match(this.search6.toLowerCase())
&& blog.user.toLowerCase().match(this.search7.toLowerCase()) );
}) // end filter()
},
sortedBlogs:function() {
return this.blogs.sort((a,b) => {
let modifier = 1;
if(this.currentSortDir === 'desc') modifier = -1;
if(a[this.currentSort] < b[this.currentSort]) return -1 * modifier;
if(a[this.currentSort] > b[this.currentSort]) return 1 * modifier;
return 0;
}); // end blogs.sort
} // end sorted blogs
}, // end computed
// declare locally - applies only to this component
filters:{
'touppercase': function(value){
return value.toUpperCase();
}
}
}// export
</script>
<style>
#show-blogs{
max-width: 800px;
margin: 0 auto;
}
#tdisplay{
margin: 20px auto;
border: 1px solid black;
border-collapse:collapse;
}
table tbody tr td{
border:1px solid black;
padding:5px;
}
table tr th{
border:1px solid black;
padding:5px;
}
a {
color: blue;
}
</style>
Its a great tutorial! Thanks for sharing it. I have successfully implemented this. Now say I have another column (an action column) which has delete button. My problem is when I sort the other columns, the button column does not get sorted at all and stays the same. How can I make sure that button column also changes when I sort any other column?
My full question is here: https://stackoverflow.com/q...
can you please answer it?
Do you have an online demo? Your SO question is about *another* code, not my demo. If you used my demo and can share an example via CodePen, I'd be happy to try.
https://codepen.io/Vibhu92/...
Here is your example which I have edited. Can you do the following on this codepen:
1. Make delete button show only for rows having Age =2
2. Make the button column stick only to the rows having Age = 2 when you sort the other columns
3. When clicked on the "delete" button, display an html alert box
1. That can be done with v-if: <button v-if="cat.age = 2">Delete</button>
2. When I tried this, it worked for me as I expected it would.
3. For that you would use Vue's event handlers, so: @click="alert('something')"
Thanks but when I use v-if="cat.age = 2" , the table only shows the rows having Age=2. Other rows are disappeared from the table view. Did you get the same ?
here is the updated codepen: https://codepen.io/Vibhu92/...
Sorry, should be ==, not =.
Cool, thanks a lot!
Hello Raymond! Thank you for great tutorial!, but its not sorted well with null value. :(
https://codepen.io/cfjedima...
so I edited code little bit to it works!
let modifier = 1;
var va = (a[this.currentSort] === null) ? "" : a,
vb = (b[this.currentSort] === null) ? "" : b;
if(this.currentSortDir === 'desc') modifier = -1;
if(va < vb) return -1 * modifier;
if(va > vb) return 1 * modifier;
return 0;
How to change `sortedCats` if sorting going on server? Is the Vue support async computed?
I'm not quite sure what your second sentence is asking. You can definitely use async/await with Vue. In my demo, all of the data is available client-side. It would absolutely be possible to build a table sorting/pagination app where the data is fetched via Ajax. I think this would be a good demo and I'll add it to my queue of stuff to write, but it IS doable in Vue.
Ok, I built this which demonstrates paging an sorting via remote APIs: https://codepen.io/cfjedima.... I'll do a blog post later on it.
Check out this update - https://www.raymondcamden.c....
Cool demo, thanks!
I believe that the sorting doesn't work fine with string values, that have empty space. I'm using the following sort function:
sort((a, b) => {
let field = this.currentSort
let modifier = 1;
if (this.currentSortDir === "desc") modifier = -1;
if (typeof a[field] === 'string') {
return modifier * ('' + a[field]).localeCompare(b[field]);
}
// console.log("Barbara Noz < Stanley Hummer ", "Barbara Noz" < "Stanley Hummer")
// console.log("Cmp: ", a[this.currentSort], " < ", b[this.currentSort], " = ", a[this.currentSort] < b[this.currentSort])
if (a[field] < b[field]) return -1 * modifier;
if (a[field] > b[field]) return 1 * modifier;
return 0;
});
Can you share what you are seeing? Ie what is incorrect. If your expectation is that it would do last name first, then I agree, it would not sort. You can try sorting by splitting on the first space, but that would break if someone did Raymond Kenneth Camden. You could sort by assuming the last space is before the last name, but that would break too if the last name had a space, like "Van Haussen".
Thanks a lot! Excellent article.
I do not usually comment on blog posts, but this tutorial is one of the easiest and most to-the-point articles I've ever seen. Thanks a lot.
You are most welcome.
Thanks a lot! You absolutely saved me because we forgot a whole page for a project and I did last minute changes with your tutorial :-) I went through a couple of tutorials/stackoverflow-answers and yours was the most understandable.
You are most welcome.
Great tutorial!
However, your api is dead :c
Thanks - will fix asap.
All fixed - thank you.
Thanks it is a great tutorial! Thanks for sharing it.I need to implement the sorting pagination for two tables in a same component.How to apply it can u help me
please mr, how can I add filter to this table, like i want to filter by name