6

We've extended the Magento class Mage_Page_Block_Template_Links using the method outlined by Sonassi here.

Editing the _construct function to include our custom template:-

protected function _construct()
{
    $this->setTemplate('page/template/links_nested.phtml');
}   

Editing the function addLink to include $childMenu variable and allow this to be used in XML layout:-

public function addLink($label, $url = '', $title = '', $prepare = false, $urlParams = array(), $position = null, $liParams = null, $aParams = null, $beforeText = '', $afterText = '', $childMenu = false)
{
    if (is_null($label) || false === $label) {
        return $this;
    }

    $link = new Varien_Object(array(
        'label' => $label,
        'url' => ($prepare ? $this->getUrl($url, (is_array($urlParams) ? $urlParams : array())) : $url),
        'title' => $title,
        'li_params' => $this->_prepareParams($liParams),
        'a_params' => $this->_prepareParams($aParams),
        'before_text' => $beforeText,
        'after_text' => $afterText,
        'child_menu' => ($childMenu ? $this->getLayout()->getBlock($childMenu) : '')
    ));

    $this->_links[$this->_getNewPosition($position)] = $link;
    if (intval($position) > 0) {
        ksort($this->_links);
    }

    return $this;
}

Then we wish to include <childMenu> parameter in local.xml for an item in topLinks:-

<reference name="top.links">
    <action method="addLink" translate="label title before_text">
    <label>Account</label>
    <url />
    <title>Account</title>
    <prepare />
    <urlParams />
    <position>10</position>
    <liParams>id="account-dropdown"</liParams>
    <aParams />
    <before_text />
    <after_text />
    <childMenu>account-submenu</childMenu>
    </action>
</reference>

And then construct the childMenu as account-submenu:-

<reference name="top.links">
<block type="page/template_links" name="submenu" as="submenu">
    <action method="setName">
    <name>account-submenu</name>
</action>
<action method="addLink" translate="label title before_text">
    <label>Contact Us</label>
    <url />
    <title>Contact Us</title>
    <prepare />
    <urlParams />
    <position>110</position>
    <liParams />
    <before_text />
    <after_text />
</action>
</block>
</reference>

Then we've made a few modifications to the template file to render childMenu if declared:-

<?php $_links = $this->getLinks(); ?>
<?php if(count($_links)>0): ?>
<ul class="links nav"<?php if($this->getName()): ?> id="<?php echo $this->getName() ?>"<?php endif;?>>
    <?php foreach($_links as $count=>$_link): ?>
        <?php if ($_link instanceof Mage_Core_Block_Abstract):?>
            <?php echo $_link->toHtml() ?>
        <?php else: ?>
            <li<?php if($_link->getIsFirst()||$_link->getIsLast()||$count): ?> class="<?php if($_link->getIsFirst()): ?>first<?php endif; ?><?php if($_link->getIsLast()): ?> last<?php endif; ?> link-<?php echo $count ?>"<?php endif; ?> <?php echo $_link->getLiParams() ?>>
                <?php echo $_link->getBeforeText() ?><a href="<?php echo $_link->getUrl() ?>" title="<?php echo $_link->getTitle() ?>" <?php echo $_link->getAParams() ?>><?php echo $_link->getLabel() ?></a><?php echo $_link->getAfterText() ?>
                <?php var_dump($_link->getChildMenu()); ?>
                <?php echo ($_link->getChildMenu()) ? $_link->getChildMenu()->toHtml() : ''; ?>
            </li>
        <?php endif;?>
    <?php endforeach; ?>
</ul>
<?php endif; ?>

Everything is working as expected apart from the fact that childMenu doesn't render anything at all in the front end, so the 'My Account' top link contains no submenu.

Is there something incorrect with the call for childMenu in the template file ?

<?php echo ($_link->getChildMenu()) ? $_link->getChildMenu()->toHtml() : ''; ?>

Code snippets sourced from sonassi.com

Ben Lessani
  • 17,630
  • 4
  • 44
  • 68
zigojacko
  • 1,754
  • 2
  • 33
  • 58
  • Yeah, erm, that code you posted is entirely ours ... I've edited your question to include an attribution to prevent copyright issues. – Ben Lessani May 20 '13 at 14:36
  • Yes I know it is. I've never claimed it is our own. Seeing you aren't responding to comments on your own blog about it, this is why I'm seeking help here... Maybe you'd care to actually contribute by advising what is needed for it to work in Magento 1.7? – zigojacko May 20 '13 at 15:10
  • 1
    Not sure where you got that idea, we're really proactive on both our own blog and SE :) – Ben Lessani May 20 '13 at 17:06
  • 3
    @GeoffJackson In case you aren't aware, Sonassi contributes quite a bit to Magento.SE. I think it's more than reasonable for him to post the appropriate attribution here. – kalenjordan May 20 '13 at 23:32
  • I'm well aware of that, I have no problem with them editing the question to include their attribution. It was the way they commented. If they can advise as per the above, that would be greatly appreciated. Thanks. – zigojacko May 21 '13 at 08:07

1 Answers1

2

There appears to be two issues with your code.

  1. The name of the sub menu item must match that of the parent's node,

  2. You must define your child menu item before the parent in the xml.

It appears that the call to $this->getLayout()->getBlock($childMenu) will return false if the child follows the parent menu item in your XML. If you update your XML as follows then it should render.

<default>
    <reference name="top.links">
        <block type="page/template_links" name="submenu" as="submenu">
            <action method="setName">
                <name>account-submenu</name>
            </action>
            <action method="addLink" translate="label title before_text">
                <label>Contact Us</label>
                <url />
                <title>Contact Us</title>
                <prepare />
                <urlParams />
                <position>110</position>
                <liParams />
                <before_text />
                <after_text />
            </action>
        </block>
    </reference>
    <reference name="top.links">
        <action method="addLink" translate="label title before_text">
            <label>Account</label>
            <url />
            <title>Account</title>
            <prepare />
            <urlParams />
            <position>10</position>
            <liParams>id="account-dropdown"</liParams>
            <aParams />
            <before_text />
            <after_text />
            <childMenu>submenu</childMenu>
        </action>
    </reference>
</default>
David Manners
  • 27,241
  • 9
  • 76
  • 220