md-data-table icon indicating copy to clipboard operation
md-data-table copied to clipboard

Multiple column ordering

Open jsenecal opened this issue 8 years ago • 22 comments

It would be nice if there was a possibility of sorting/ordering on more than one column at a time.

From JSON:API:

An endpoint MAY support multiple sort fields by allowing comma-separated (U+002C COMMA, ",") sort fields. Sort fields SHOULD be applied in the order specified.

GET /people?sort=age,name HTTP/1.1
Accept: application/vnd.api+json

The sort order for each sort field MUST be ascending unless it is prefixed with a minus (U+002D HYPHEN-MINUS, "-"), in which case it MUST be descending.

GET /articles?sort=-created,title HTTP/1.1
Accept: application/vnd.api+json

The above example should return the newest articles first. Any articles created on the same date will then be sorted by their title in ascending alphabetical order.

jsenecal avatar Aug 12 '15 18:08 jsenecal

Hmm... this might be tricky. It looks like ng-repeat supports ordering by multiple properties with the following syntax,

<div ng-repeat="item in items | orderBy: ['one', 'two']">

My first thought is, how do you control multi-column sorting in the UI in a way that is obvious to the user?

daniel-nagy avatar Aug 12 '15 18:08 daniel-nagy

In my case i'm ordering server side - does this make a difference to you ?

I was thinking that the order should be applied in the order it was clicked.

ie -> click name then id would sort by "name" then by "ID" if after that you re-click name, then you would sort by ID and then by name.

clicking twice the same thing would change ascending/descending.

jsenecal avatar Aug 12 '15 20:08 jsenecal

In my case i'm ordering server side - does this make a difference to you ?

No, we just need to make sure it is compatible with ng-repeat. I think setting the order as an array of strings is fine. If the developer needs a different format for their query language they can just process the array in their md-trigger function.

I was thinking that the order should be applied in the order it was clicked.

ie -> click name then id would sort by "name" then by "ID" if after that you re-click name, then you would sort by ID and then by name.

clicking twice the same thing would change ascending/descending.

The issue is, the user needs a way of controlling whether clicking a second column mean to sort using both columns or to only sort on the column they just clicked. Otherwise the array of items to sort on would grow without restriction.

We need some way of requiring the user to indicate that they would like to sort on multiple columns, maybe require them to hold the command key as they click multiple columns? I don't know if that would be obvious to the user or not.

daniel-nagy avatar Aug 12 '15 20:08 daniel-nagy

I guess the CTRL + Click option is a good one, you could leave the actual explanation to the front end dev.

jsenecal avatar Aug 13 '15 20:08 jsenecal

I'd suggest using a 3-state switch for sorting instead of a modifier key so it can be done on mobile devices as well. So it would go in this order: ascending, descending, no sort.

And the order of sorting is of course as @jsenecal suggested:

ie -> click name then id would sort by "name" then by "ID" if after that you re-click name, then you would sort by ID and then by name.

But it would be a nice thing to have some sort of a visual representation of this. A small number next to the sort arrow maybe, like the one mentioned here: http://ux.stackexchange.com/a/34790/2538

gligoran avatar Aug 14 '15 13:08 gligoran

@gligoran the three-state switch is an option, not an option that I am very fond of but it would work on mobile where as the key + click option would not.

We can't necessarily enforce the [ascending, descending, no sort.] order. It may be beneficial for some applications to first sort descending so we would need to provide that as an option.

If we are concerned about multi-column sort on mobile then key + click is out

daniel-nagy avatar Aug 14 '15 13:08 daniel-nagy

With the way things are developing everywhere at the moment, I think mobile should have the same capabilities as a desktop PC.

Of course that should be configurable, I was trying to show what I mean by 3-state.

gligoran avatar Aug 14 '15 13:08 gligoran

I agree, I believe developing apps for mobile browsers is just as important as developing apps for desktop browsers. The irony though is that data tables are inherently bad for mobile devices. I really question, from a UX perspective, if tables should be used at all on mobile devices.

daniel-nagy avatar Aug 14 '15 14:08 daniel-nagy

@gligoran +1 for your tri-state idea - it seams like the perfect behavior but I think it should be debounced to prevent API calls when cycling the options ...

jsenecal avatar Aug 14 '15 17:08 jsenecal

datatables and ui-grid are using shift-click for multiple column ordering/sorting.

On a click, sort list is cleared and only one column is sorted. On a shift-click, tri-state for the column is changed and column is added to the sort list if not present. state "no sort" removes the column from the sort list.

See: https://datatables.net/examples/basic_init/multi_col_sort.html http://ui-grid.info/docs/#/tutorial/102_sorting

antoinebrault avatar Aug 18 '15 20:08 antoinebrault

@antoinebrault shift-click will not work on devices without a keyboard. Maybe we could use a gesture on mobile? For example, double tap to add a column to the sort list.

daniel-nagy avatar Aug 18 '15 20:08 daniel-nagy

@daniel-nagy Yeah I think you could figure out something for mobile devices. However, I don't think you should restrict desktop features based on the fact that it's hard to use on mobile. Maybe you could support multiple column ordering in general, bind shift-click for desktop and make another issue to figure out later how to do it for mobile (switch, gesture, etc.)

antoinebrault avatar Aug 19 '15 13:08 antoinebrault

@antoinebrault That is probably what I will do, I just want to make sure when I (or someone else if they want :smiley:) develop this we isolate the logic from the actual method for triggering it so we can easily go back later and make it work with mobile.

We also need to think about how we are going to detect mobile devices without included additional libraries. Maybe checking for touch events on the window object is sufficient.

daniel-nagy avatar Aug 19 '15 13:08 daniel-nagy

Do you actually have to determine what kind of a device it is? I'm thinking that you could have both SHIFT click and double click/tap work side by side. This way you cover all devices without knowing their type and add desktop users an additional option how to multi-sort.

gligoran avatar Aug 19 '15 13:08 gligoran

@gligoran You wouldn't need to check for a specific device necessarily but I don't think it would be wise to register listeners for touch events if they are not defined in the browser. While it may not have much of an effect on performance, I think it would be better to not make the browser do more work than it needs to.

daniel-nagy avatar Aug 19 '15 14:08 daniel-nagy

@daniel-nagy , Has this been implemented Daniel? I am also in need of this feature..

rusiarohit avatar Aug 29 '16 22:08 rusiarohit

I think like @jsenecal. CTRL + Click is a good one. I want too this feature.

ferchoman09 avatar Sep 21 '16 19:09 ferchoman09

Hi, any update on that feature?

kenji-getpowered avatar Nov 25 '16 08:11 kenji-getpowered

Any news about it? I still need multi-column ordering

lehno avatar Dec 07 '16 10:12 lehno

Hi. Any news about this feature?

kaiosilveira avatar Mar 23 '17 15:03 kaiosilveira

I am in need of this feature too. I really like the implementation of the rest of the component. Would love to have this implemented. Any word on if it is being worked on or the state it is in?

br8kpoint avatar May 18 '17 20:05 br8kpoint

Using Bootstrap and Lodash.... For multi-column server-side ordering with this tool, I disabled the sort display in the column headers, then show a list of buttons of the current sort order, green with an up caret or red with a down caret. When you click on one of these buttons, it removes the sort. If you click on a column, it either adds the field to the sort, makes it the first field to sort by, or inverses the sort order if it's already the first field to sort by. I have done 3-column background sort column colors instead, but this is what I've done with this particular tool.


$scope.sort = [];
$scope.removeSort = function (item) {
  if (item) $scope.sort = _.filter($scope.sort, s => {
    return s !== item;
  });
  $scope.applySort();
}
$scope.orderData = function (field) {
  var target = field.indexOf('-') == 0 ? field.substr(1): field;
  $scope.sort = _.filter($scope.sort, s => {
    return s !== target && s != '-' + target;
  })
  $scope.sort.unshift(field);
  $scope.applySort();
}
$scope.applySort = function () {
  $scope.criteria.sorts = _.map($scope.sort, (d) => {
    var field = d.indexOf('-') === 0 ? d.substr(1): d;
    var direction = d.indexOf('-') === 0 ? 'DESC': 'ASC';
    return { attribute: field, order: direction };
  });
  $scope.loadData();
}

Then I make my buttons like this (inside a toolbar):

<span class="filtersList pull-right m-l-lg m-b-sm" ng-if="sort.length>0">
    <span class="title m-r-xs">Sorting:</span>
    <span ng-repeat="item in sort" ng-init="sortAsc = item.indexOf('-') !== 0; sortName = sortAsc ? item: item.slice(1)">
      <button class="btn btn-xs m-l-xs" ng-class="sortAsc ? 'btn-danger': 'btn-info'" ng-click="removeSort(item)"><i class="fa m-r-xs" ng-class="sortAsc ? 'fa-chevron-down':'fa-chevron-up'"></i>{{ sortName }}</button>
    </span>
</span>

Inside my md-table, I do this:

<thead md-head md-order="order" md-on-reorder="orderData">

I've got added complexity in the orderData process because my server for this particular project wants the sort array expressed as an array of objects instead of an array of field-name strings.

mckinleymedia avatar Oct 16 '17 20:10 mckinleymedia