Zend_Navigation Tricks: True tab navigation with sub menus – Part 1

It is some what tricky with the Zend_Navigation menu helpers to set up your typical tab-based navigation with sub pages relevant to the tab your on, as seen below. But it’s not far difficult so don’t be put off, hopefully the view helpers will improve over time.

tab-menu-example

In the mean time this is a 3 part series in achieving the navigation I set up in utilitiesman.com as seen above.

Part 1: Setting up the navigation, and rendering the tabs.

Set up your navigation configuration, I’ve done this in xml.

< ?xml version="1.0" encoding="UTF-8"?>
<configdata>
    <nav>
        <label>Home</label>
        <module>default</module>
	<controller>index</controller>
	<action>index</action>
        <pages>
            <computers>
                <label>Computers</label>
                <module>computers</module>
                <controller>index</controller>
                <action>index</action>
                <pages>
                    <networking>
                        <label>Networking</label>
                        <module>computers</module>
                        <controller>networking</controller>
                        <action>index</action>
                        <pages>
		                    <ipaddress>
		                        <label>IP Address</label>
		                        <module>computers</module>
		                        <controller>networking</controller>
		                        <action>ipaddress</action>
		                    </ipaddress>
		                    <ping>
		                        <label>Ping</label>
		                        [... code removed for example ...]
		                    </ping>
     	                            [... code removed for example ...]
		                </pages>
                    </networking>
                    <security>
                        [... code removed for example ...]
                    </security>
                </pages>
            </computers>
            <measures>
                [... code removed for example ...]
            </measures>
        </pages>
    </nav>
</configdata>

In your bootstrap file you’ll need setup the navigation and load your navigation config:

$navigationConfig = new Zend_Config_Xml('./application/Config/navigation.xml');
$navigation = new Zend_Navigation($navigationConfig);

Assuming you’re making use of the Zend_Layout this would go in your template

$this->navigation()->menu()->setPartial(array('nav1.phtml','default'));
echo $this->navigation()->menu()->render();

This is my partial menu template which is where some minor trickery is performed to see the Home page and first level pages in a single <ul> for easy application of CSS to make the <li>’s look like tabs. This is the “nav1.phtml” referred to in the layout.

    echo '<ul id="nav1">';
    // loop root level (only has Home, but later may have an Admin root page?)
    foreach ($this->container as $page) {
        // check if it is active (not recursive)
        $isActive = $page->isActive(false);
        $liClass = $isActive ? ' class="active"' : '';
        echo '<li ' . $liClass . '>' . $this->menu()->htmlify($page) . '</li>', PHP_EOL;
        // loop next level
        foreach ($page as $page) {
            // check if it is active (recursive)
            $isActive = $page->isActive(true);
            $liClass = $isActive ? ' class="active"' : '';
            echo '<li ' . $liClass . '>' . $this->menu()->htmlify($page) . '</li>', PHP_EOL;
        }
    }
    echo '</ul>';

What the partial template above renders is something like this, neatly all in a single hieratical level..

<ul id="nav1">
    <li><a ...>Home</a></li>
    <li class="active"><a ...>Computers</a></li>
    <li><a ...>Measures</a></li>
</ul>

6 Responses to “Zend_Navigation Tricks: True tab navigation with sub menus – Part 1”

  • Zend_Navigation – the first touch « How to use it Says:

    [...] had found some strange tutorials like Zend_Navigation Tricks: True tab navigation with sub menus – Part 1 | Child of the Machine , but do not understand why that complexity is needed as default output of component makes exactly [...]

  • The first impression isn’t always correct « How to use it Says:

    [...] the first impression isn’t always correct. In my previous post, I quite sceptically mentioned Zend_Navigation Tricks: True tab navigation with sub menus tutorial. In this post I finally publish my tests with Zend_Navigation to find out was I right or [...]

  • Jan Malte Says:

    could you just tell us how to extend your nav1.phtml to use ACL for just displaying the tabs which the user has the permission to access?

  • Grant Perry Says:

    Hi Jan. There is a getPrivilege() method on $page from Zend_Navigation_Page. I understand Zend_Navigation and Zend_Acl work well together so I suspect this will help you figure out what you’re trying to do… Presuming getPrivilege() does what I’d have though, you’d use an if statement deciding whether or not to echo the list item tags. I hope this helps sorry I haven’t had to do this yet with the tabs myself.

  • John Says:

    This can all be much more easily done without partials and PHP code.

    In your top level nav for your tabs just add:

    echo $this->navigation()->menu()->setMaxDepth(0);

    Then in the sub-navigation just add:

    echo $this->navigation()->menu()->setMinDepth(1)->setMaxDepth(1)->setOnlyActiveBranch(1)->setRenderParents(false);

    Voila. Done :) All you’ll need to do is define how the unordered list styles and list items should be displayed. Then set a class for active on a list item and you’ll be all set.

    No need for php code in partials to do something that Zend Framework already has built in! :)

  • Grant Perry Says:

    John thanks for your suggestions – I’ll take another look to see if I can simplify this solution.

    At the time of writing I had thought I’d explored all of the simple ZF built ins, but didn’t have any luck. Most attempts produced results that weren’t quite what I was after with HTML which is why I ended up using partials for their greater flexibility.

    E.g. For the top level nav I was looking to render the items from 2 depths in a single level of a < .ul.> for the simplicity of my CSS, I believe using the setMaxDepth(0) here would render it as nested < .ul.>‘s?

    As for your suggestion for the sub navigation I’ll test it out and see if it has the desired result!

Leave a Reply