How to Add Sorting & Ordering of Columns in Joomla Component

The state variables list.ordering and list.direction are used to store the ordering column and ordering direction (ascending or descending). The filter form is used for the ordering and sorting field. In the model, you have to allowable columns in the $config array.

Step 1: Filter Form

forms/filter_planets.xml

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

<fields name="list">
        <field
            name="fullordering"
            type="list"
            label="JGLOBAL_SORT_BY"
            class="js-select-submit-on-change"
            default="a.id DESC"
            validate="options">
            <option value="">JGLOBAL_SORT_BY</option>
            <option value="a.ordering ASC">JGRID_HEADING_ORDERING_ASC</option>
            <option value="a.ordering DESC">JGRID_HEADING_ORDERING_DESC</option>
            <option value="a.published ASC">JSTATUS_ASC</option>
            <option value="a.published DESC">JSTATUS_DESC</option>
            <option value="a.title ASC">JGLOBAL_TITLE_ASC</option>
            <option value="a.title DESC">JGLOBAL_TITLE_DESC</option>
            <option value="a.created_by ASC">JAUTHOR_ASC</option>
            <option value="a.created_by DESC">JAUTHOR_DESC</option>
            <option value="a.created ASC">JDATE_ASC</option>
            <option value="a.created DESC">JDATE_DESC</option>
            <option value="a.hits ASC" requires="hits">JGLOBAL_HITS_ASC</option>
            <option value="a.hits DESC" requires="hits">JGLOBAL_HITS_DESC</option>
            <option value="a.id ASC">JGRID_HEADING_ID_ASC</option>
            <option value="a.id DESC">JGRID_HEADING_ID_DESC</option>
        </field>

        <field
            name="limit"
            type="limitbox"
            label="JGLOBAL_LIST_LIMIT"
            default="25"
            class="js-select-submit-on-change" />

</fields>

We are adding many columns for ordering. For each column, there are two directions - ascending and descending. The default is descending order by id.

When the value of the field is changed, the form is submitted. The populateState() method of the ListModel explodes the fullordering field and stores into state variables list.ordering and list.direction.

Step 2: Model File

src/Model/PlanetsModel.php

1. Query

In the model file, which gets the data from the table, in the method 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 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));

2. Allowable Columns

You need add the names of all columns by which the data can be sorted to the 'filter_fields' config array.

public function __construct($config = [])
{
    $config['filter_fields'] = array(
        'id', 'a.id',
        'title', 'a.title',
        'alias', 'a.alias',
        'published', 'a.published',
        'created', 'a.created',
        'modified', 'a.modified',
        'access', 'a.access',
        'hits', 'a.hits',
    );

    parent::__construct($config);
}

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

Step 3: View File

src/View/Planets/HtmlView.php

After generating the sorting variables in the model, you need to get the state variables in the view file as well. These will be used in template layout file for changing table column headers. 

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

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

Step 4: Layout File - Column Headers

tmpl/planets/default.php

You need to replace the static column header names with searchtools.sort HTMLHelper 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. This is used to display the arrow signs on the table headings.

<th><?php echo HTMLHelper::_('grid.checkall'); ?></th>
<th>
<?php echo HTMLHelper::_('searchtools.sort', 'JSTATUS', 'a.published', $this->listDirn, $this->listOrder); ?>
</th>
<th>
<?php echo HTMLHelper::_('searchtools.sort', 'JGLOBAL_TITLE', 'a.title', $this->listDirn, $this->listOrder); ?>
</th>
<th>
<?php echo HTMLHelper::_('searchtools.sort', 'JGRID_HEADING_ID', 'a.id', $this->listDirn, $this->listOrder); ?>
</th>

In the backend, now you can also sort by clicking on the column headers.