15

In my module, I'm using TableSort for some of my tables, but I also have some tables that are generated by code, so not directly linked to a query. These tables are also created with theme('table') and so have the $header and $rows arrays. Is it possible to use TableSort on those as well, maybe with writing my sorting function?

The documentation for tablesort.inc seems to suggest it is possible (All tables created with a call to theme('table') have the option of having column headers that the user can click on to sort the table by that column). However, I haven't found any instructions or example on how to do this. Everything I found so far is based on a query. I'm using Drupal 7.

10

Tablesort actually consists of two different systems which work together.

The first part is the rendering, the stuff that happens directly within theme_table() or is called from that. All it does is display the table headers with the sort indication if a default sort or override through $_GET is present and makes them links so that you can click on them.

The second part is the TableSort query extender, that adjusts the query it is added on based on the default sort direction or the $_GET override.

These two systems are actually pretty separated, the just work together easily because they get their data from the same $header structure and use the same helper functions and naming conventions for the $_GET parameters. But nothing stops you from using only one of these.

To actually answer your question, if you just need the rendering part, you just need to make sure to do something similar to TableSort::orderbyHeader(). Instead of the orderBy() call, you'd use a array sort function, or pass it as an argument to a web service or anything else.

And for the opposite, you'd just need to make sure that you display a link that is basically the equivalent of tablesort_header() so that it is recognised by the TableSort query extender.

  • Thank you for pointing me in the right direction, I got it working now. For those trying to achieve the same, I put my steps in a separate answer as it doesn't fit in a comment field. – Whiskey Nov 7 '11 at 10:30
15

Thanks to Berdir I got it working. This is how it works in more detail.

Tablesort is triggered "automatically" if the (column) arrays in the $headers array contains the keys 'data', 'field' and optionally 'sort'. This will create links with 'sort' and 'order' in the column headers and show the little arrow and such.

To do your own sorting, get the current sort settings with tablesort_get_order and tablesort_get_sort and use those values for your own sorting function. The key 'sql' in the array returned by tablesort_get_order contains the field name to be used for sorting.

A piece of (untested) example code with the array $users containing some details for each user:

// setup the table data that we want to show
$tableData = array();
foreach ($users as $userDetails) {
  $tableData[] = array(
      'name' => $userDetails['name'],
      'visits' => $userDetails['visits'],
      'views' => $userDetails['views'],
      'comments' => $userDetails['comments']
  );
}

// headers array, sorting by default on comments
$headers = array(
    array('data' => t('Name'), 'field' => 'name'),
    array('data' => t('Visits'), 'field' => 'visits'),
    array('data' => t('Views'), 'field' => 'views'),
    array('data' => t('Comments'), 'field' => 'comments', 'sort' => 'desc')
);

// getting the current sort and order parameters from the url
$order = tablesort_get_order($headers);
$sort = tablesort_get_sort($headers);

// sort the table data accordingly (write your own sort function)
$tableData = my_array_sort($tableData, $order['sql'], $sort);

// create the array with rows for theme table
$rows = array();
foreach ($tableData as $entry) {
  $rows[] = array(
      array('data' => $entry['name']),
      array('data' => $entry['visits']),
      array('data' => $entry['views']),
      array('data' => $entry['comments']),
  );
}

// add any attributes and sent everything to theme table
$attributes = array('class' => array('my_class'));
$table = array('header' => $headers, 'attributes' => $attributes, 'rows' => $rows);
$html = theme('table', $table);
4

Here is the code that i ended up on the answer of whiskey. It uses entity field query.

 $query = new EntityFieldQuery();
  $query
  ->entityCondition('entity_type', 'vehicle')
  ->entityCondition('bundle', 'car');
  $result=$query->execute();
  $ids=array_keys($result['vehicle']);
  $values=entity_load('vehicle',$ids);
  $rows=array();
  foreach($values as $val){
    $rows[]=array('data'=>array(
      'id'=>$val->id,
      'title'=>$val->title,
      'price'=>$val->field_price['und'][0]['value'],
      'model'=>$val->field_model['und'][0]['value'],
      'color'=>$val->field_color['und'][0]['value'],
      'speed'=>$val->field_speed['und'][0]['value'],

    ));
  }


  // We are going to output the results in a table with a nice header.
  $header = array(
    // The header gives the table the information it needs in order to make
    // the query calls for ordering. TableSort uses the field information
    // to know what database column to sort by.
    array('data' => t('Entity Id'),'field' => 'id'),
    array('data' => t('Title'),'field' => 'title'),
    array('data' => t('Price'),'field' => 'price'),
    array('data' => t('Model'),'field'=>'model'),
    array('data' => t('Color'),'field'=>'color'),
    array('data' => t('Speed'),'field'=>'speed'),

  );

  $order = tablesort_get_order($header);
  $sort = tablesort_get_sort($header);
  $sql=$order['sql'];
  if($sort=='desc') {

    usort($rows, function($a, $b) use($sql) {
    return $a['data'][$sql] > $b['data'][$sql]? -1 : 1;

  });

  }
  if($sort=='asc') {
      usort($rows, function($a, $b) use ($sql) {
        return $a['data'][$sql] < $b['data'][$sql]? -1 : 1;
      });
  }

  $output = theme('table', array(
    'header' => $header,
    'rows' => $rows,
  ));

  return $output;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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