vuetifyjs / vuetify

🐉 Vue Component Framework
https://vuetifyjs.com
MIT License
39.8k stars 6.96k forks source link

[Feature Request] v-data-table header:sort function should be passed entire row, not just cell #11226

Closed gregveres closed 9 months ago

gregveres commented 4 years ago

Problem to solve

consider that you have a table of first name in one column and last name in the other column. There is going to be a high probability that multiple entries have the same first name. There is also going to be a high probability that multiple entries will have the same last name.

A good sort for the first name column will be to sort by the first name while also doing a sort on the last name when duplicate first names are detected. This will result in a well sorted list by first name.

The same happens when sorting the last name. A good solution is to break the tie based on the first name.

This seems to be impossible with the header sort function of the v-data-table because the sort function seems to be passed the cell values (first name or last name) only and not the entire record for that row.

I understand that you might come back with "use the custom sort prop" for something like this, but that seems like drastic overkill for something as simple as this problem and as prevalent as this problem.

Proposed solution

I recognize that if you change the signature of that custom sort function now, it will break all existing code. I propose that you add two arguments to the sort function after the a and b arguments that are there already.

export type DataTableCompareFunction<T = any> = (a: T, b: T) => number

would become:

export type DataTableCompareFunction<T = any, R = any> = (a: T, b: T, ra: R, rb: R) => number

where R is the record type.

Since this function will be called a number of times, maybe having 4 arguments rather than 2 arguments is too much overhead. Another approach would be to add a second sort function with the same signature, but instead of passing in T, you would be passing in R.

export interface DataTableHeader<T extends any = any> {
  text: string
  value: string
  align?: 'start' | 'center' | 'end'
  sortable?: boolean
  filterable?: boolean
  divider?: boolean
  class?: string | string[]
  width?: string | number
  filter?: (value: any, search: string | null, item: any) => boolean
  sort?: DataTableCompareFunction<T>,
  sortWithItem?: DataTableCompareFunction<T>
}
sugoidesune commented 4 years ago

Came to request the same Feature. I am doing quite complicated sorts, based on multiple fields. I am currently filling the data with additional computed entries (which have to stay dynamic) , for others I include a UID to lookup the row. All of this requires a lot of extra code and moving parts.

adamsol commented 3 years ago

Let me also suggest that if a new sorting callback is added, it would be probably more convenient if it worked like iteratees in Lodash's sortBy or key in Python's sort, i.e. by returning a sorting key for each item, instead of requiring us to compare two items and return a number.

s0m3on3 commented 2 years ago

Any progess on that?

grolu commented 1 year ago

We also rely on the raw item data for sorting. We have custom rows and within a singe cell we show data from multiple props from a deep object structure. We also show icons and other classifiers that users can search for. The header keys actually don't exist on the raw object...

Right now we solve this issue by also sort outside of the <v-data-table> and overwrite all sorting functions with a dummy function like this:

customKeySort = {
  name: () => 0,
  ...
}

This prevents <v-data-table> sorting internally. But this is obviously a hack and we don't want to release like this.

The ideal solution for us would be to get back the old custom-sort callback where we got passed all items and could deal with them to execute our complicated sorting which depends on multiple fields and values that need to be calculated on-the-fly.

Employee87 commented 11 months ago

I have requested this same feature in the past with no responses.

https://github.com/vuetifyjs/vuetify/issues/17816

I essentially want to define my sort function but get back the 2 item row values instead of the cell values.