vue.jsvuetify.js

v-data-table sorting, capture and control current sorting criteria


Vue 3.5.13, Vuetify 3.8.5

I display a data table, allowing the user to use multi-sorting, so that they can sort by various combinations of columns. Under some circumstances I want to show the data is a particular sort order, and then offer to restore the user's previously selected sort order. To that end, I want to watch the current sort value, store that for later use.

I have a variable

:sort-by.sync="sortBy"

const sortBy = ref([]);

And after mounting assign a value to that variable.

   (sortBy.value = [
    { key: 'calories', order: 'asc' },
    { key: 'fat', order: 'desc' },
  ])

This works correctly. Further, I watch that variable and display its value when it changes.

My expectation was that when the user now selects a new sort order my variable would be updated -I use :sort-by.sync

I do not see the watch trigger. Is it possible to obtain the currently active sort criteria by this, or any other means?

The example code below is modified from the multi-sort example in the v-data-table docuemntation.

I've added a display of the value of a sortBy variable. This variable is set when the applciation is mounted, and we see the wat ched sortBy value as it is set.

<template>
  <h1>{{ msg }}</h1>
  <v-data-table
    :headers="headers"
    :items="desserts"
    :sort-by.sync="sortBy"
    multi-sort
  ></v-data-table>
</template>

<script setup>
  import { ref, watch, onMounted, computed } from 'vue'
  const sortBy = ref([])
  const msg = ref('x')

  onMounted(() => {
    watch(
      () => sortBy.value,
      () => {
        msg.value = 'Sorting by ' + JSON.stringify(sortBy.value)
      }
    )
  })

  onMounted(
    () =>
      (sortBy.value = [
        { key: 'calories', order: 'asc' },
        { key: 'fat', order: 'desc' },
      ])
  )

  const headers = [
    {
      title: 'Dessert (100g serving)',
      align: 'start',
      sortable: false,
      key: 'name',
    },
    { title: 'Calories', key: 'calories' },
    { title: 'Fat (g)', key: 'fat' },
    { title: 'Carbs (g)', key: 'carbs' },
    { title: 'Protein (g)', key: 'protein' },
    { title: 'Iron (%)', key: 'iron' },
  ]
  const desserts = [
    {
      name: 'Frozen Yogurt',
      calories: 200,
      fat: 6,
      carbs: 24,
      protein: 4,
      iron: 1,
    },
    {
      name: 'Ice cream sandwich',
      calories: 200,
      fat: 9,
      carbs: 37,
      protein: 4.3,
      iron: 1,
    },
    {
      name: 'Eclair',
      calories: 300,
      fat: 16,
      carbs: 23,
      protein: 6,
      iron: 7,
    },
    {
      name: 'Cupcake',
      calories: 300,
      fat: 3.7,
      carbs: 67,
      protein: 4.3,
      iron: 8,
    },
    {
      name: 'Gingerbread',
      calories: 400,
      fat: 16,
      carbs: 49,
      protein: 3.9,
      iron: 16,
    },
    {
      name: 'Jelly bean',
      calories: 400,
      fat: 0,
      carbs: 94,
      protein: 0,
      iron: 0,
    },
    {
      name: 'Lollipop',
      calories: 400,
      fat: 0.2,
      carbs: 98,
      protein: 0,
      iron: 2,
    },
    {
      name: 'Honeycomb',
      calories: 400,
      fat: 3.2,
      carbs: 87,
      protein: 6.5,
      iron: 45,
    },
    {
      name: 'Donut',
      calories: 500,
      fat: 25,
      carbs: 51,
      protein: 4.9,
      iron: 22,
    },
    {
      name: 'KitKat',
      calories: 500,
      fat: 26,
      carbs: 65,
      protein: 7,
      iron: 6,
    },
  ]
    </script>

Solution

  • .sync modifier only exists in Vue 2.

    Use v-model in Vue 3:

      <v-data-table
        :headers="headers"
        :items="desserts"
        v-model:sort-by="sortBy"
        multi-sort
      ></v-data-table>
    

    Ref: https://v3-migration.vuejs.org/breaking-changes/v-model