I'm sorting table columns in Joomla Backend. I adjust settings according to this tutorial.
As we can see it is suggested to override populateState
method and manually obtain sorting options.
public function populateState() {
$filter_order = JRequest::getCmd('filter_order');
$filter_order_Dir = JRequest::getCmd('filter_order_Dir');
$this->setState('filter_order', $filter_order);
$this->setState('filter_order_Dir', $filter_order_Dir);
}
But I noticed that the native component com_content
does not set these options explicitly in the model file administrator/components/com_content/models/articles.php
.
protected function populateState($ordering = null, $direction = null)
{
// Initialise variables.
$app = JFactory::getApplication();
$session = JFactory::getSession();
............................................
............................................
............................................
// List state information.
parent::populateState('a.title', 'asc');
}
Instead it just invokes parent populateState
. And in fact JModelList::populateState()
includes this:
protected function populateState($ordering = null, $direction = null)
{
// If the context is set, assume that stateful lists are used.
if ($this->context) {
$app = JFactory::getApplication();
.....................................
.....................................
.....................................
$value = $app->getUserStateFromRequest($this->context.'.ordercol', 'filter_order', $ordering);
if (!in_array($value, $this->filter_fields)) {
$value = $ordering;
$app->setUserState($this->context.'.ordercol', $value);
}
$this->setState('list.ordering', $value);
// Check if the ordering direction is valid, otherwise use the incoming value.
$value = $app->getUserStateFromRequest($this->context.'.orderdirn', 'filter_order_Dir', $direction);
if (!in_array(strtoupper($value), array('ASC', 'DESC', ''))) {
$value = $direction;
$app->setUserState($this->context.'.orderdirn', $value);
}
$this->setState('list.direction', $value);
}
else {
$this->setState('list.start', 0);
$this->state->set('list.limit', 0);
}
}
So I'm trying to imitate the code of the native com_content
. Thus I assume that
class CompViewData extends JView
{
function display($tpl = null)
{
$this->state = $this->get('State');
Will invoke parent JModelList::populateState()
(so I'm not overriding it in the modal class) and set $this->setState('list.ordering', $value);
. But for some reason when I invoke $this->state->get()
in getListQuery()
to build my SQL query with ordering
protected function getListQuery()
{
$orderCol = $this->state->get('list.ordering', 'id');
$orderDirn = $this->state->get('list.direction', 'asc');
This variables happen to be not defined.
What am I missing? I assume it is somehow connected with proper user session, but I don't have evidence whatsoever.
After just coming across the same issue I found that, as you said, the superclass populateState() does indeed have the behaviour defined. However, it also does a check to ensure your field is in the "whitelist".
if (!in_array($value, $this->filter_fields))
If you look at com_content you will see this section at the top of the model class (in your case models/articles.php):
public function __construct($config = array())
{
if (empty($config['filter_fields']))
{
$config['filter_fields'] = array(
'id', 'a.id',
'title', 'a.title',
//...(more fields here)
'publish_up', 'a.publish_up',
'publish_down', 'a.publish_down',
);
$app = JFactory::getApplication();
$assoc = isset($app->item_associations) ? $app->item_associations : 0;
if ($assoc)
{
$config['filter_fields'][] = 'association';
}
}
parent::__construct($config);
}
You will need to include this section so that the ModelList class knows that the 'ordering' field is in the whitelist. Obviously substitute the fields with those on which you wish to filter.
The Joomla JModelList
defines populateState
like this
protected function populateState($ordering = null, $direction = null)
It means that if you do not have populateState
override in you class, this will be called but it gets no values. The minimum requirement is to set default values if you want to use ordering. You may completely delete this method from your class if you are not planning to use ordering at all.
So, minimum what you need is to interpolate in your class
protected function populateState($ordering = null, $direction = null) {
parent::populateState('id', 'ACS');
}
Otherwise you will not get anything in $state->get()
or $this->state->get()
unless you click on ordering column. Then parent's populateState
will take variables from request.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With