There are several steps required so that sorting works properly. The state variables list.ordering and list.direction are used to store the ordering column and ordering direction (ascending or descending).

Step 1: Filter Form

To keep track of the current column for ordering and direction, use the list["fullordering"] field. This is displayed on the form as well.

<fields name="list">
<field
name="fullordering"
type="list"
label="COM_HELLOWORLD_LIST_FULL_ORDERING"
description="COM_HELLOWORLD_LIST_FULL_ORDERING_DESC"
onchange="this.form.submit();"
default="greeting ASC">
<option value="">JGLOBAL_SORT_BY</option>
<option value="greeting ASC">COM_HELLOWORLD_ORDERING_ASC</option>
<option value="greeting DESC">COM_HELLOWORLD_ORDERING_DESC</option>
<option value="id ASC">JGRID_HEADING_ID_ASC</option>
<option value="id DESC">JGRID_HEADING_ID_DESC</option>
<option value="published ASC">COM_HELLOWORLD_PUBLISHED_ASC</option>
<option value="published DESC">COM_HELLOWORLD_PUBLISHED_DESC</option>
<option value="author ASC">COM_HELLOWORLD_AUTHOR_ASC</option>
<option value="author DESC">COM_HELLOWORLD_AUTHOR_DESC</option>
<option value="created ASC">COM_HELLOWORLD_CREATED_ASC</option>
<option value="created DESC">COM_HELLOWORLD_CREATED_DESC</option>
</field> 

When the value of the field is changed, the form is submitted. The populateState() function of the List Model explodes this field and stores into state variables list.ordering and list.direction.

Step 2: Model File

In the model file, which generates the data that will form the table, in the function getListQuery(), before returning the query, you need to get these two state variables. Then, adjust the query so that the order parameters are taken into account.

// Add the list ordering clause
$orderCol = $this->state->get('list.ordering', 'id');
$orderDirn = $this->state->get('list.direction', 'desc');

$query->order($db->escape($orderCol) . ' ' . $db->escape($orderDirn));

Step 3: View File

After generating the sorting variables in the model, you need to get in the view file.

// Get application
$app = JFactory::getApplication();
$context = "helloworld.list.admin.helloworld";

$this->state = $this->get('State');

$this->filterForm = $this->get('FilterForm');
$this->activeFilters = $this->get('ActiveFilters');

Step 4: Template File

Then, you can assign these variables from the state variables in your template file.

$listOrder = $this->escape($this->state->get('list.ordering'));
$listDirn = $this->escape($this->state->get('list.direction'));

 

Step 5: Column Headers - Template File

You need to replace the static column names with searchtools.sort Jhtml static class. The first argument must be 'searchtools.sort'. The second argument is the name of the column that you actually see in the Joomla Administration List View.

The third argument is the name of the corresponding database field (column) that is to be sorted on. This is passed to the model. The fourth and the fifth arguments are the current order direction (asc or desc) and the name of the column that the table is currently sorted on.

For example,

<th width="2%"> 
<?php echo JHtml::_('searchtools.sort', 'JGRID_HEADING_ID', 'id', $listDirn, $listOrder); ?>
</th>

Step 6: Allowable Columns - Model File

You need add the names of all columns by which your data can be sorted to the 'filter_fields' config, like this:

public function __construct($config = array())
{
// Allowable Columns
$config['filter_fields'] = array('column_name_1', 'column_name_2', 'column_name_3');
parent::__construct($config);
}

If you use column prefixes in your query, you can also specify them along with the column name (like 'a.id').