sortingdatatablevuejs3vuetify.js

Omiting Items During Sort in Vuetify Datatable


I want to filter out null values when sorting on the averageScore column of my datatable. Currently, when sorting on the averageScore column, null values are treated as the lowest value, so they come out on top when sorting ascending. I want them to be at the bottom at all times when sorting is active on that column. It would be even better if I can filter them out when sorting is active.

Here is a simplified version of the code:

<script setup lang="ts">

const headers = [
    {
        title: "Name",
        key: "name"
    },
    {
        title: "AverageScore",
        key: "averageScore"
    },
];

const items = [
    { name: "Item1", averageScore: 5 },
    { name: "Item2", averageScore: 4 },
    { name: "Item3", averageScore: 3 },
    { name: "Item4", averageScore: 1 },
    { name: "Item5", averageScore: null }
];


function getColorScore(score: number) {
    if (score === null) return "white";
    if (score <= 2) return "red";
    else if (score === 3) return "yellow-darken-3";
    else if (score <= 5) return "green";
}



</script>

<template>
    <v-data-table
        :items="adminStore.polls"
        :headers="headers as any"
    >
        
        <template #[`item.averageScore`]="{ value }">
            <v-chip class="px-5" :color="getColorScore(value)">{{ value }}</v-chip>
        </template>
        
    </v-data-table>
</template>

I've tried custom-key-sort but couldn't get it to work, I've also tried custom-sort but it seems to be deprecated (I think). The sort attribute in the header seemed to work, but I can't change the behavior depending on if the sorting is asc or desc.


Solution

  • Check this out: playground

    You can check if the data table has enable the sortBy by adding a flag sortByActivated

    <v-data-table
        :items="filteredItems"
        :headers="headers"
        @update:options="onOptionsUpdate"
      >
    ...
    
    onOptionsUpdate(options) {
      this.sortByActivated = options.sortBy?.length > 0
    }, 
    

    and replace the items with filtered items:

    computed: {
      filteredItems() {
        if (!this.sortByActivated) {
          return this.items
        }
        return this.items.filter(item => item.averageScore !== null)
      },
    },