Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get current sort options when sort changes in vuetify data tables

Tags:

vuetify.js

Our tables pagination and sorting are all done on the server, but I still want to allow the user to click column headers to sort. I need to access the tables sort options when the sorting changes. It seems the events are split

update:sort-by
update:sort-desc

I could create two methods, have the first event set the column (sort-by) value, and then the second method actually trigger the sort. But that sounds horrible and prone to race conditions or future bugs.

It would be better if the sort-by included the desc/asc data as well. I tried creating a ref to the table, but for some reason the properties containing the sort information are empty.

The event update:options contains all the necessary information, but that could fire for reasons other than sorting which isn't ideal either.

So I'm not sure if I'm missing something here. Is there a better way to accomplish this?

                                <v-data-table
ref="contractItemTable"
:headers="headers"
:items="contracts"
:disable-sort="isLoadingPage"
:server-items-length="tableTotal"
disable-pagination
hide-default-footer
@click:row="navigateToContract"
single-select
@update:sort-by="sortTable"
@update:sort-desc="sortTable"
item-key="id.id">

And the JS

public sortTable(event) {

    console.debug(this.$refs.contractItemTable.sortBy);
    console.debug(this.$refs.contractItemTable.sortDesc);
}

No matter what I click, the sortBy and sortDesc properties are empty. If I use the options event, the event contains the correct sortBy and sortDesc. But as stated above, not exactly the event I want to use. I have it working, but I have to "ignore" the initial load options event since it's not a valid time for this method to fire.

like image 550
cphilpot Avatar asked May 04 '26 21:05

cphilpot


2 Answers

You're mostly there (and found your question while trying to sort out the best way to apply sorting to derived/computed column-items myself) ... just need to bind the v-data-table sort-by and sort-desc attributes to data elements so that you can refer to them in your sortTable function:

<v-data-table
    ...
    :items="contracts"
    :headers="headers"
    :sort-by.sync="sortBy"
    :sort-desc.sync="sortDesc"
    @update:sort-by="sortTable"
    @update:sort-desc="sortTable"
    ...
>

export default {
    data() {
        contracts: [],
        sortBy: 'contractDate',  // make sure this matches headers[].value
        sortDesc: false, // and both match your initial from-server sort
        ...
        headers: [
            { text: 'Contract Date', sortable: true, value: 'contractDate' },
            { text: 'Contract Value', sortable: true, value: 'contractValue' }
            ...
        ]


    },
    methods: {
        sortTable() {
            if(this.sortBy === 'contractDate') {
                this.contracts.sort( (a,b) => {
                    return ( a.contractDate > b.contractDate ? 1 : -1 ) * (this.sortDesc ? -1 : 1 );
                });
            }
            if(this.sortBy === 'contractValue') {
                this.contracts.sort( (a,b) => {
                    return ( a.contractValue > b.contractValue ? 1 : -1 ) * (this.sortDesc ? -1 : 1 );
                });
            }
            
        }
    }
}

Your sort logic obviously will vary, but included the Array.sort() callback example there to show where this.sortDesc is used to reverse the evaluation.

A big caveat to be aware of is that if you do not specify

<v-data-table :must-sort="true" >

Then the bound @update:sort-by and @update:sort-desc events will BOTH fire when sort is deactivated which happens when user clicks the same column header a third time (it cycles through sorted to no-sort states.)

To get around this, add something like

sortPending: false 

to your data state, and when the event fires, return immediately out of the event if this.sortPending === true, and move your sort logic into a Vue.nextTick() callback:

    methods: {
        sortTable() {
            if(this.sortPending) return;
            this.sortPending = true;
            this.$nextTick( () => {
                this.sortPending = false;
                /* your sort logic here */
            });
like image 136
storsoc Avatar answered May 07 '26 03:05

storsoc


In data table add attribute:

:sort-desc.sync="sort_desc"

In data:

sort_desc:true,//or what you need by default

In observable:

sort_desc:function(val,_prev){
    //do what you need to change sort and refresh
},
like image 35
Luca C. Avatar answered May 07 '26 03:05

Luca C.



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!