8

I have a view (Drupal 6 / Views 2, but I think this may apply to other versions as well) displayed as a sortable table. I can add fixed sort criteria as you can with all views, but once the table is sorted by the visitor on a certain table, those sort criteria are ignored.

In the style options there is a box called "Override normal sorting if click sorting is used", which doesn't make sense to me. It seems to effectively disable click sorting, leaving the end user with a clickable but not working table headers.

Is there a way to keep the fixed sort criteria and use them as secondary criteria?

7 Answers 7

3

The initial sorting that you have specified in views is only used on the first page view. When you click on the header to change the sort the query is altered to use the drupal table sort routines instead. Unfortunately there is no support in the built in table sort code to allow multiple column sort, nor the ability to define a default of descending instead of ascending column. An alternative if your table is displaying all results is to add some Javascript that performs table sorts on the HTML and not provide sorting on the columns in Views. A google.com search for "javascript table sort" will give many results, this one looks to be quite robust: http://tablesorter.com/docs/

4
  • Thanks, I hadn't considered a javascript-based solution yet. I'd rather do this with php/sql, but I'll take a look. Commented Jun 16, 2011 at 8:40
  • The only other easy solution is to create sort criteria in Views, then expose the ones you want people to be able to sort by. The table header sorting issue will still exist, but at least with the exposed sorts they will be able to choose multiple sort options. In this case Views should obey the exposed sorts in the order that they are defined.
    – codexmas
    Commented Jun 16, 2011 at 13:29
  • 1
    and there is Views integration with Tablesorter: drupal.org/project/views_tablesorter
    – keva
    Commented Jun 16, 2011 at 14:00
  • For D7 as well: drupal.org/project/tablesorter
    – leymannx
    Commented Jul 28, 2014 at 15:06
3

As others said before

there is no support in the built in table sort code to allow multiple column sort, nor the ability to define a default of descending instead of ascending column

But you should have a look at the following approach with Tablesorter.

For D7:

1.Download and enable Tablesorter Module

2.Download and extract Tablesorter jQuery Plugin into sites/all/libraries/tablesorter

3.Add a CSS class tablesorter and an unique id to your Views tables in template.php

/**
 * Preprocess variables for Views tables.
 */
function YOUR_THEME_preprocess_views_view_table(&$vars) {
  $view = $vars['view'];
  $vars['classes_array'][] = 'tablesorter';
  $vars['attributes_array']['id'] = $view->name . '-' . $view->current_display;
}

4.Clear cache a few times. Now Tablesorter should already start to work. You'll see it when the styling changed.

5.For secondary sort you need to add a small custom JavaScript. In template.php:

/**
 * Override or insert variables for the page templates.
 */
function YOUR_THEME_preprocess_page(&$vars) {
    // you might define some conditions around here
    drupal_add_js(drupal_get_path('theme', 'YOUR_THEME') . '/scripts/custom_tablesort.js');
}

6.In that script write the following to tell Tablesorter to sort the first six collumns of certain tables in ascending alphabetical order. To tell Tablesorter to sort only the second and third column in ascending order write sortList: [[1,0], [2,0]] instead.

(function ($) {
  Drupal.behaviors.tableSorting = {
    attach: function (context, settings) {

      $("#your_view_name-display_name").tablesorter({
        sortList: [[0,0],[1,0],[2,0],[3,0],[4,0],[5,0]]
      });

    }
  }
}) (jQuery);

If you want to let Tablesorter secondary sort all your tables you don't need to define a CSS id when preprocessing and simply tell Tablesorter: $("table").tablesorter({ sortList: [[0,0],[1,0],[2,0],[3,0],[4,0],[5,0]] });

After a little testing I'ld say you leave any custom Tablesorter option out (finish with step 4) and simply explain your users that while holding down shift when clicking multiple headers, secondary sorting works on every desired column they want.

1
  • 1
    Thanks, I'll definitely try this if I ever need it again. Commented Aug 12, 2014 at 10:00
2

Remove the "Default Sort" from the Table settings and use the "Sort Criteria" for the first and second order

1

From the question what I get is that you want a table sorter function in Views; if it is so, you can follow the following steps:

  1. Edit the view you want to add the column sorting to.
  2. Under "Basic Settings", look for "Style: Table" and click on the picture of a cog next to it.
  3. Scroll down to see the table settings.
  4. There is a list of the fields, and a tickbox for each labelled "sortable"; tick the boxes for any columns you want users to be able to change the sort order on.
1
  • Thanks, but that's not what I'm looking for. I know how the default table sorting works. What I want is a default sort option that becomes the secondary sort order when the user clicks a table header. For instance, a table is sorted alphabetically by default, but when a user clicks the author column, the table is sorted by author first, while rows with the same author are still sorted alphabetically. Commented Nov 3, 2011 at 12:24
1

(D8)

After lots of debugging I ended up with similar D7 approach D7 hook_views_query_alter

It boils down to using triggering the table style plugins clickSort method.

  • Create a sub folder named multisort in modules.
  • Safe the code below as multisort.module into folder created above.

<?php

use Drupal\views\Plugin\views\query\QueryPluginBase;
use Drupal\views\ViewExecutable;

/**
 * Implements hook_views_query_alter().
 */
function multisort_views_query_alter(ViewExecutable $view, QueryPluginBase $query) {

  $views_to_alter = [
    // view name
    'sort_test' => [
      [
        'table' => 'node__field_col_a',
        'field' => 'field_col_a',
        'column' => 'field_col_a_value',
        'order' => 'desc',
      ],
    ]
  ];

  if (isset($views_to_alter[$view->id()])) {
    //dpm($query->orderby, 'by config or url');

    $fields_used = [];
    foreach($query->orderby as $field) {
      $fields_used[$field['field']] = 1;
    }

    $fields = $views_to_alter[$view->id()];

    foreach($fields as $field) {
      // Skip fields already clicked
      if (isset($fields_used[$field])) {
        continue;
      }

      $alias = $field['table'] . '.' . $field['column'];
      if (isset($fields_used[$alias])) {
        continue;
      }

      // @see \Drupal\views\Plugin\views\style\Table::buildSortPost
      $view->field[$field['field']]->clickSort($field['order']);
    }

    //dpm($query->orderby, 'altered');

  }
}

  • Save text below into multisort.info.yml

name: Multisort
type: module
description: Sort on more then one field
core: 8.x
package: Views

1

This is my solution in D7/Views 3. It adds a last order_by clause to the query if its not already present. I believe you could look at the $view parameter and add the order by columns from there if you dont want to do it statically like I did.

function MODULENAME_views_query_alter(&$view, &$query) {
  if ($view->name == 'the_name_of_the_view_to_alter') {
    //First check that we don't already sort by the "the_field_alias" column
    if(array_search('the_field_alias', array_column($query->orderby, 'field')) === FALSE) {
      //Add the "the_field_alias" column last in the orderby array
      $query->orderby[] = [
        'field' => 'the_field_alias',
        'direction' => 'ASC',
      ];
    }
  }
}
0
0

Edit the views and go to Table settings there you can see sorting checkbox... you can checked and apply..

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.