Adding a Boolean Toggle to a grid in Joomla admin

Joomla has a fantastic tutorial on MVC components on it’s website, but it seems to stop way short of explaining how to make a fully featured admin panel.

One of the features it doesn’t seem to explain well is how to add those little green ticks and red circles that you can click and it changes (toggles) from one to the other.

Joomla Demo - Administration - Google Chrome_2013-04-30_16-55-57

I like to use it for chosing if an item will appear on the front page or not – but I’m sure you could think of other uses for it. Joomla also has a built in ‘Published’ button which is a bit simpler, so I’ll start from that and move on up.

Above is a screenshot of the finished product. You can see that I have green ticks/red circles for Published and for Front Page.

Publish is based on the field `published` in your table. It can’t be anything else. It must be an integer field with a 1 or a 0 as the value.

First, you can generate the tick really easily in your template code

Add the following to admin/views/people/tpl/default_body.php:

$published = JHTML::_('grid.published', $item, $i );

This will produce the green tick or red cross depending if the value of ‘published’ is 1 or 0.

Clicking on the tick is going to need some more code:

Add the following to admin/controller.php:

       /**
         * Set the item to be published
         */
        function publish()
        {
        	// Check for request forgeries
        	JRequest::checkToken() or jexit( 'Invalid Token' );

        	// Get some variables from the request
        	$menutype = JRequest::getVar('menutype', '', 'post', 'menutype');
        	$cid	= JRequest::getVar( 'cid', array(), 'post', 'array' );
        	JArrayHelper::toInteger($cid);

        	$model = $this->getModel( 'People' );
        	if ($model->setItemState($cid, 1)) {
        		$msg = JText::sprintf( 'People Published', count( $cid ) );
        	} else {
        		$msg = $model->getError();
        	}
        	$this->setRedirect('index.php?option=com_people&view=people' . $menutype, $msg);
        }

        /**
         * Set the item to be not published
         */
        function unpublish()
        {
        	// Check for request forgeries
        	JRequest::checkToken() or jexit( 'Invalid Token' );

        	// Get some variables from the request
        	$menutype = JRequest::getVar('menutype', '', 'post', 'menutype');
        	$cid	= JRequest::getVar( 'cid', array(), 'post', 'array' );
        	JArrayHelper::toInteger($cid);

        	$model =& $this->getModel( 'People' );
        	if ($model->setItemState($cid, 0)) {
        		$msg = JText::sprintf( 'People Unpublished', count( $cid ) );
        	} else {
        		$msg = $model->getError();
        	}
        	$this->setRedirect('index.php?option=com_people&view=people', $msg);
        }

That will create functions that will be executed when the boolean toggle is clicked.

Then, create this function in admin/models/people.php:

    /**
	* Set the published value of the given person
	*/
    function setItemState( $items, $state )
    {
        if(is_array($items))
        {
            foreach ($items as $id)
            {
                $db = JFactory::getDbo();
                $query = $db->getQuery(true);
                $query->update('#__people_person')
                      ->set('`published`='.$state)
                      ->where('`id`='.$id);
                $db->setQuery($query);
                $db->execute();
            }
        }
    }

That will perform the actual update on the table. That’s it. Now you can click on the tick or circle and it will toggle the published status. Of course you need to adapt the SQL on the site end to display it or not based on the published field – but I’ll leave that to you.

But what about other boolean fields – such as front page? Joomla provides a framework for a custom boolean field. Simply use the following code in place of the above:

InĀ admin/views/people/tpl/default_body.php:

 $front_page     = JHTML::_('grid.boolean', $i, $item->front_page,'frontPage','unFrontPage');?>

Here we are specifying that the field type is boolean, the row number in the grid, the boolean value (1 or 0) and the functions to toggle the value on and off.

The functions we saw earlier in this tutorial called ‘publish’ and ‘unpublish’ can be copied to make ‘frontPage’ and ‘unFrontPage’ – or any function names that you like.

Add the following to admin/controller.php:

        /**
         * Set the item to be published
         */
        function frontPage()
        {
                // Check for request forgeries
                JRequest::checkToken() or jexit( 'Invalid Token' );

                // Get some variables from the request
                $menutype = JRequest::getVar('menutype', '', 'post', 'menutype');
                $cid    = JRequest::getVar( 'cid', array(), 'post', 'array' );
                JArrayHelper::toInteger($cid);

                $model = $this->getModel( 'People' );
                if ($model->setItemFrontPage($cid, 1)) {
                        $msg = JText::sprintf( 'People put on front page', count( $cid ) );
                } else {
                        $msg = $model->getError();
                }
                $this->setRedirect('index.php?option=com_people&view=people' . $menutype, $msg);
        }

        /**
         * Set the item to be not published
         */
        function unFrontPage()
        {
                // Check for request forgeries
                JRequest::checkToken() or jexit( 'Invalid Token' );

                // Get some variables from the request
                $menutype = JRequest::getVar('menutype', '', 'post', 'menutype');
                $cid    = JRequest::getVar( 'cid', array(), 'post', 'array' );
                JArrayHelper::toInteger($cid);

                $model =& $this->getModel( 'People' );
                if ($model->setItemFrontPage($cid, 0)) {
                        $msg = JText::sprintf( 'People removed from front page', count( $cid ) );
                } else {
                        $msg = $model->getError();
                }
                $this->setRedirect('index.php?option=com_people&view=people', $msg);
        }

Lastly, create this function in admin/models/people.php:

        /**
        * Set the published value of the given person
        */
    function setItemFrontPage( $items, $state )
    {
        if(is_array($items))
        {
            foreach ($items as $id)
            {
                $db = JFactory::getDbo();
                $query = $db->getQuery(true);
                $query->update('#__people_person')
                      ->set('`front_page`='.$state)
                      ->where('`id`='.$id);
                $db->setQuery($query);
                $db->execute();
            }
        }
    }

That will update the table setting the value of `front_page` to 1 or 0.

And that’s it. Now you can toggle published status and a custom status like ‘front page’.

Enjoy!