1

I'm currently working on sorting functionality on a table built with vue.js. I have ascending sorting currently working with numbers. However I am unable to get the descending and alphabetical functionality to work properly.

Here is my html where I am calling the sort functionality. Currently I have this as a method().

     <tr class="dash-table-mainHead">
              <th 
                v-for="(column, key) in columns"
                :key="key"
                @click="sortTable(column)"
              >{{ column.label }}</th>
            </tr>

Here is the javascript where I have my array of columns with appropriate fields.

  data() {
        return {
            columns: [
                { label: this.$t('reporting.source'), field: 'source' },
                { label: this.$t('reporting.accountsWithActivity'), field: 'accountsWithActivity', align: 'center', type: 'icon' },
                { label: this.$t('reporting.answerableConversations'), field: 'answerableConversations', type: 'boolean', align: 'center' },
                { label: this.$t('reporting.interactiveConversations'), field: 'interactiveConversations', type: 'boolean', align: 'center' },
                { label: this.$t('reporting.leads'), field: 'leads', align: 'center' },
                { label: this.$t('reporting.interactiveLeadConversations'), field: 'leads', type: 'date' },
                { field: 'blank' },
            ],

            convertedData: [],
            // currentSort: 'name',
            currentSortDir: 'asc',

        }
    },

And finally my method where I am doing the sorting. This currently works for ascending only and doesn't appear to be sorting alphabetically.

methods: { sortTable(column) {
            console.log(column.field)
            let sortedData = [];

            sortedData = this.convertedData.sort((a, b) => {
                if (a[column.field] < b[column.field]) { return -1; }
                if (a[column.field] > b[column.field]) { return 1; }
                return 0;
            })
            }
        }

1 Answer 1

1
  1. Use a computed property sortedData for your items and put that in your template instead of convertedData
  2. If comparing strings, use String.localCompare.
  3. Add a sortField data property.
  4. Simply set the sortField to null or your clicked field value to make the magic happen.
@click="sortField=column.field"

let component = {
  data() {
    return {
      // convertedData: ...
      sortField: null,
      currentSortDir = 'asc'
    }
  },
  computed: {
    sortedData() {
      if (this.sortField === null) {
        return this.convertedData;
      }
      return this.convertedData.sort((a, b) => {
        let res;
        if (typeof a[this.sortField] === 'string') {
          res = a[this.sortField].localeCompare(b[this.sortField])
        } else {
          res = a[this.sortField] > b[this.sortField] ? 1 :
            a[this.sortField] < b[this.sortField] ? -1 : 0
        }
        if (this.currentSortDir !== 'asc') {
          ret = ret * -1;
        }
        return ret
      })
    }
  }
}

If you have null/undefined values you will have to do some more work checking the types.

It is now very easy to sort multiple fields. And the sort direction can be reactive as well by just updating the sort direction data property.

Sign up to request clarification or add additional context in comments.

1 Comment

We will need more code posted then. You do not show where your computed data comes from, or where your template loops the data.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.