4

i am using a template for which there are two different navigation menu.

  1. Main navigation menu. ( fixed )

  2. Action navigation menu, contains elements such as back, save, delete etc. this navigation elements changes according to the controllers being called. while it may exist for some controller and for some it doesn't

i am making use of layout, and i have placed all the template code in my default.phtml layout file. the problem i face is for action navigation menu. since the html code for this menu resides in default.phtml i need to change the content of it according to the controller being called.

i am not sure if this is the right way of doing it. but in my default.phtml i am checking the controller name and accordingly displaying the menu. this is the code i am using.

<?php if(Zend_Controller_Front::getInstance()->getRequest()->getControllerName() == 'item'): ?>
    <!-- Action Navigation Menu -->
    <div class="statsRow">
        <div class="wrapper">
            <a href="#"><img src="/images/icons/dark/add.png" alt="" class="icon"><span>New item</span></a>
            <a href="#"><img src="/images/icons/dark/cd.png" alt="" class="icon"><span>Publish / Unpublish item</span></a>
            <a href="#"><img src="/images/icons/dark/trash.png" alt="" class="icon"><span>Delete item</span></a>
        </div>
    </div>
    <div class="line"></div>
<?php endif; ?>

is it okay to do it like this? or do i have any better way of doing this?

Liyali
  • 5,643
  • 2
  • 26
  • 40
Ibrahim Azhar Armar
  • 25,288
  • 35
  • 131
  • 207

2 Answers2

3

It seems that your Action navigation menu acts actually like a SubMenu, where each Action is part of a subpage. A good way to do such a thing is to have two instances of Zend_Navigation, that you could store in the registry for example. Then, in your controllers, you could call an Action Helper in the preDispatch() method like this:

// in each controller where you want your "action navigation menu"
public function preDispatch()
{
    $this->_helper->navigation()->renderActionNavigation();
}

Of course, only controllers that need this Action navigation menu would have this method. This Action Helper will basically get the current view object, create a placeholder and render a partial as follows:

// in your library/My/Controller/Action/Helper
class My_Controller_Action_Helper_Navigation extends Zend_Controller_Action_Helper_Abstract
{
    private $_view = null;

    public function direct()
    {
        $this->_view = $view = Zend_Layout::getMvcInstance()->getView();
        $this->_view->placeholder('action-navigation');
        return $this;
    }

    public function renderActionNavigation()
    {
        $this->_view->render('partials/_action-navigation.phtml');
    }
}

In case you don't use a library, simply put this code in /views/helpers/ and rename the class Zend_View_Helper_Navigation.

Then the partial will be in charge to render your subMenu using a placeholder:

// in /view/scripts/partials/_action-navigation.phtml
<?php $this->placeholder('action-navigation')->captureStart() ?>
<?php $options = array('onlyActiveBranch' => true); ?>
<?= $this->navigation()->menu()->renderMenu(Zend_Registry::get('nav.action-navigation'), $options);
// here I assume that you've stored your Navigation container in the registry ?>
<?php $this->placeholder('action-navigation')->captureEnd() ?>

Additionally, rendering your menu using the navigation view helper method renderMenu() with an option onlyActiveBranch set to true will allow your to only render the active branch, where each branch would correspond to your controllers.

And finally, in your layout you would have this:

 // in your layout file (usually named layout.phtml)
<?= $this->placeholder('action-navigation'); ?>

If you choose to register your Zend_Navigation container in the registry, this could be done in the bootstrap this way:

// in your bootstrap.php
protected function _initNavigation()
{
    $config = new Zend_Config_Xml(APPLICATION_PATH . '/configs/navigation.xml', 'nav');
    $container = new Zend_Navigation($config);
    Zend_Registry::set('nav.action-navigation', $container);
}

For more information about containers, refer to this page. Also, if you're not familiar with placeholders, here is a good practical example about how to use them.

Liyali
  • 5,643
  • 2
  • 26
  • 40
  • i am new to zend framework. and your explanation seems to be a bit overhead for me. i am still grasping the concept of helpers or navigation and how it is handled in zend. could you please explain me on what and all is happening with the code. and where does it belong – Ibrahim Azhar Armar Apr 08 '12 at 15:48
  • Just edited my answer and added comments on each snippet. From the Zend Documentation, [Action Helpers](http://framework.zend.com/manual/en/zend.controller.actionhelpers.html#zend.controller.actionhelper.writingyourown) allow developers to inject runtime and/or on-demand functionality into any Action Controllers that extend `Zend_Controller_Action`. **Action Helpers** aim to minimize the necessity to extend the abstract Action Controller in order to inject common Action Controller functionality. – Liyali Apr 08 '12 at 17:12
  • i appreciate your help. but do you think i can achieve the same without using Zend_Navigation?. what is bothering me about Zend_Navigation is custom decorators i am still not able to get it. how about using the View helpers for the same purpose? – Ibrahim Azhar Armar Apr 10 '12 at 14:06
  • You can always override Zend Navigation view helpers to make them act the way you want. However, I recommend you to keep Zend_Navigation component to render your navigation, it makes things easier in most cases. – Liyali Apr 10 '12 at 17:16
  • i am getting this error `script 'partials/_action-navigation.phtml' not found in path (./views/scripts/)` i am using a modular directory structure and i am placing the partials in `application/layouts/partials` directory i am not able to get this to work. how do i change the path to work with partials with respect to my directory structure?. – Ibrahim Azhar Armar Apr 12 '12 at 06:26
  • Add a new viewscript path. For instance in a controller: `$this->view->addScriptPath(APPLICATION_PATH . "/layouts/partials");`. You could also do the same thing in the bootstrap in an `_initView()` method. – Liyali Apr 12 '12 at 08:04
  • yeah, i did and it worked thanks to you, however i am still faced with the problem of decorating it in the partial. :) – Ibrahim Azhar Armar Apr 12 '12 at 08:37
  • You want to change the rendered html? If so, you would need to override the Navigation view helper. – Liyali Apr 12 '12 at 08:42
  • is there a way i could send data from action helper to view partial. i tried using `$this->view->mykey = 'myvalue';` nothing seems to work – Ibrahim Azhar Armar Apr 12 '12 at 09:42
  • Send them as an array through the second argument of the [partial() method](http://framework.zend.com/manual/en/zend.view.helpers.html#zend.view.helpers.initial.partial). – Liyali Apr 12 '12 at 10:14
  • i have posted the followup question of this topic. i will be thankful if you could have a look at it http://stackoverflow.com/questions/10266946/action-based-navigation-in-zend-framework thank you :) – Ibrahim Azhar Armar Apr 22 '12 at 10:12
1

I guess it's ok. I'd instead do it in the controller and include the navigation using Zend_Navigation, then you can make use of the ACL etc.

If the controller just set:

$this->view->navigation()->setContainer($navigation);

Where $navigation is an instance of Zend_Navigation. Then in your layout:

<?=$this->navigation()->menu()?>
Ashley
  • 5,939
  • 9
  • 39
  • 82
  • can i use zend_navigation to produce the exact same syntax for my menu? could you please provide me with an example.:) – Ibrahim Azhar Armar Apr 08 '12 at 15:49
  • See http://stackoverflow.com/questions/1243697/getting-zend-navigation-menu-to-work-with-jquerys-fisheye/1255289#1255289 – Ashley Apr 08 '12 at 18:46
  • the problem with your approach is i need to define action navigation for all the controller and action. while for my app the action navigation exist for some and for some it doesn't – Ibrahim Azhar Armar Apr 10 '12 at 16:11