19 Dec 2010

Checkboxes in ExtJs TreeGrid

Recently I had to create a TreeGrid with checkable nodes using ExtJs. I used Ext.ux.tree.TreeGrid component for it, but it doesn't shows checkboxes like the standard TreePanel do. As I didn't found quick solution to this problem I had to fix it myself by modifying Ext.ux.tree.TreeGridNodeUI for this purpose:

It follows the same logic as the standard TreeGrid component - if node contains the "checked" parameter set to true or false then a checkbox will be shown in the tree node.

 

4 Dec 2010

FlashMessenger view helper for Zend Framework

In Zend framework flash messages feature is implemented as the controller action and I often used it like this:

Add message to flash messenger.

$flashMessenger = $this->_helper->getHelper('FlashMessenger');
$flashMessenger->addMessage('We did something in the last request');

… later on, in another page, retrieve it.

$flashMessenger = $this->_helper->getHelper('FlashMessenger');
$messages = $flashMessenger->getMessages();

If I need to specify the status of my message – success, error or something else the messenger namespaces can be used:

// For success messages.
$flashMessenger->setNamespace('success');
$flashMessenger->addMessage('Success!');

// For notices.
$flashMessenger->setNamespace('notice');
$flashMessenger->addMessage('Some notice');

Namespace has to be set before adding or retreiving messages from helper. So, we have to manually retrieve messages from all namespaces, then we can pass them to view and style them according to their status.

To simplify my work with flash messenger I created the view helper that can set namespace and add message in one line. Also it can retrieve and display messages in a view automatically. You can use it as follows:

// file controllers/UserController.php
public function editAction(){
    $form = new User_Form();
    if ($this->_request->isPost()) {
        if ($form->isValid($_POST)) {
            // .. save user data
            $this->view->flashMessenger('success')->addMessage('Data successfully saved');
            $this->view->flashMessenger('notice')->addMessage('Note! This is a test data.');
            $this->_redirect('/user/list');
        }
    }
}

The example show the edit action whery the user data is validated, saved and then we use flash messenger helper to set success message. After that the redirect occurs to the ‘/user/list’ action. To show message in the list action we use the same flash messenger view helper:

// file views/scripts/user/list.phtml
<?= $this->flashMessenger() ?>

The flash messenger automatically scan through all defined namespaces and shows messages in the following form:

<ul class="flashSuccess">
    <li>Data successfully saved</li>
</ul>
<ul class="flashNotice">
    <li>Note! This is a test data.</li>
</ul>

The class name for each block has prefix “flash” followed by the name of namespace, which you can choose on your own – error, success, notice, info etc. Also you can pass the namespace as a parameter for the helper to show only its messages:

<?= $this->flashMessenger('info'); ?>

To use the view helper you need 2 files:

1. App/View/Helper/FlashMessenger.php

<?php
/**
 * FlashMessenger View Helper
 */
class App_View_Helper_FlashMessenger extends Zend_View_Helper_Placeholder_Container_Standalone
{
    /**
     * View namespace.
     * 
     * @var type string
     */
    protected $_namespace;

    /**
     * Prefix that is prepended before every class name of the message block
     *
     * @var string
     */
    protected $_classPrefix = 'flash';

    /**
     * Instance of FlashMessenger
     *
     * @var App_Controller_Action_Helper_FlashMessenger
     */
    protected $_flashMessenger;

    public function __construct()
    {
        parent::__construct();

        $this->_flashMessenger = new App_Controller_Action_Helper_FlashMessenger();
    }

    public function flashMessenger($namespace = null)
    {
        $this->setNamespace($namespace !== null ? $namespace : 'default');
        $this->_namespace = $namespace;

        return $this;
    }

    /**
     * Set namespace for flash messenger.
     * 
     * @param string $namespace 
     */
    public function setNamespace($namespace)
    {
        $this->_flashMessenger->setNamespace($namespace);
    }


    /**
     * Add message in flash messenger.
     * 
     * @param string $msg
     */
        public function addMessage($msg)
        {
        $this->_flashMessenger->addMessage($msg);
        }

    /**
     * Render messages.
     *
     * @param string|int $indent
     * @return string
     */
    public function toString($indent = null)
    {
        $str = $this->getPrefix();

        if ($this->_namespace) {
            $namespaces = array($this->_namespace);
        } else {
            $namespaces = $this->_flashMessenger->getAvailableNamespaces();
        }

        foreach ($namespaces as $namespace) {
            $str .= $this->render($namespace);
        }

        $str .= $this->getPostfix();

        return $indent.$str;
    }

    /**
     * Render particular namespace.
     * 
     * @param type $namespace
     * @return string 
     */
    public function render($namespace)
    {
        $str = '';

        $this->_flashMessenger->setNamespace($namespace);
        $messages = $this->_flashMessenger->getMessages();

        if (count($messages) > 0) {

            $str .= '<ul class="'.$this->_classPrefix.ucfirst($namespace).'">';

            foreach ($messages as $message) {
                $str .= '<li>'.$message.'</li>';
            }

            $str .= '</ul>';
        }

        return $str;
    }

}

2. App/Controller/Action/Helper/FlashMessenger.php

<?php
class App_Controller_Action_Helper_FlashMessenger
    extends Zend_Controller_Action_Helper_FlashMessenger {

    public function getAvailableNamespaces()
    {
        $namespaces = array();

        if (count(self::$_messages) > 0) {
            foreach (self::$_messages as $namespace=>$values) {
                $namespaces[] = $namespace;
            }
        }

        return $namespaces;
    }
}

The action helper is needed to be able to get list of defined namespaces. Both files have to be in library path and the App/View/Helper plugin path has to be defined for Zend_View instance.

Another solution that solve the same problem in slightly different way can be found at ZFSnippets web site: Grouped FlashMessenger View Helper

20 Nov 2010

Greetings

Hello world! This is my first post at posterous.

Dmitri Ischenko's Space

I'm a freelance web developer. I create web apps using JavaScript, NodeJS, PHP, Zend.