How to add static blocks to main navigation dropdown?

How to add static blocks to main navigation dropdown?

forwardcom@sxc.hu

Many stores require some additional information in the main navigation drop-down section. Displaying only subcategories might not always be enough and I noticed this is becoming a trend on shopping sites now days. Although there are many ways to accomplish this (including building you own custom module) I would like to show you a more clever way that will allow you to use static blocks and easily connect them with product categories. To better understand what I am talking about see the sample image of the end result below.

Static block in main navigation

The idea

Magento 1.6 and earlier
The general idea is to use static blocks because they are easily editable and can hold many different types of content. The problem with static blocks is that you cannot assign them directly to product categories in Magento, or can you? Here’s an idea, set the “Identifier” value of the static block to be the same as the “URL Key” of the desired category. Now you have a logical connection between your static block and a product category. We just have to display the appropriate static blocks in the main navigation drop-down.

Magento 1.7
Now, in version 1.7 Magento introduced a completely new way of rendering menu items (thanks Johnboy for reminding me) that require some changes for this to work. The general idea is the same as above (for Magento 1.6) but this time we need to use something else instead of “URL Key” to connect our static block to a category. This time we will use the category ID value with a simple string prefix.

The implementation

Magento 1.6 and earlier
To implement this simple idea we need to override a core Magento block class and add a few lines of code to a single function. How simple is that :)

  1. First we need to override the core Magento block class by copying the block file from core to local folder. We are going to use “Mage_Catalog_Block_Navigation”class so we need to copy:
    /app/code/core/Mage/Catalog/Block/Navigation.php

    to

    /app/code/local/Mage/Catalog/Block/Navigation.php

    If you don’t have a folder structure in your local folder you will need to create it.

  2. Find the protected function _renderCategoryMenuItemHtml (should begin at around line 218). This is the function that will render all the menu items which is exactly what we need.
  3. Now find this piece of code (lines 309-312):
    $html[] = '<ul class="level' . $level . '">';
    $html[] = $htmlChildren;
    $html[] = '</ul>';
    
  4. Add the following code just above the line with the closed ul tag:
    $staticBlock = trim($this->getLayout()->createBlock('cms/block')->setBlockId(strtolower($category->getUrlKey()))->toHtml());
    if(!empty($staticBlock)){
    	$html[] = '<span class="nav-static-block" style="background:#fff; border-top:1px solid #ccc; padding:10px;">';
    	$html[] = $staticBlock;
    	$html[] = '</span>';
    }
    

    The end result should look like this:

    $html[] = '<ul class="level' . $level . '">';
    $html[] = $htmlChildren;
    $staticBlock = trim($this->getLayout()->createBlock('cms/block')->setBlockId(strtolower($category->getUrlKey()))->toHtml());
    if(!empty($staticBlock)){
    	$html[] = '<span class="nav-static-block" style="background:#fff; border-top:1px solid #ccc; padding:10px;">';
    	$html[] = $staticBlock;
    	$html[] = '</span>';
    }
    $html[] = '</ul>';
    

    The implementation is simple, check if there is a static block with the identifier value that is the same as the current category URL Key. If so, add the static block to the menu.

    I used some inline CSS for the sake of simplicity but you should use your own.

  5. Now you need to create a static block with the identifier value set to whatever category URL Key you want and you are all done! I used the default Magento sample data and created a static block with the identifier set to “furniture” because that is the URL Key of the Furniture category.

Magento 1.7
This time we need to override a different Magento core class because in 1.7 Magento uses  Mage_Page_Block_Html_Topmenu to render the main menu.

  1. First we need to override the core Magento block class by copying the block file from core to local folder. We need to copy:
    /app/code/core/Mage/Page/Block/Html/Topmenu.php

    to

    /app/code/local/Mage/Page/Block/Html/Topmenu.php

    If you don’t have a folder structure in your local folder you will need to create it.

  2. Find the protected function _getHtml (should begin at around line 84).
  3. Now find this piece of code (lines 121-123):
    $html .= '<ul>';
    $html .= $this->_getHtml($child, $childrenWrapClass);
    $html .= '</ul>';
    
  4. Add the following code just above the line with the closed ul tag:
    $staticBlock = trim($this->getLayout()->createBlock('cms/block')->setBlockId($child->getId())->toHtml());
    if(!empty($staticBlock)){
    	$html .= '<span style="background:#fff; border-top:1px solid #ccc; padding:10px;">';
    	$html .= $staticBlock;
    	$html .= '</span>';
    }
    

    The end result should look like this:

    $html .= '<ul class="level' . $childLevel . '">';
    $html .= $this->_getHtml($child, $childrenWrapClass);
    $staticBlock = trim($this->getLayout()->createBlock('cms/block')->setBlockId($child->getId())->toHtml());
    if(!empty($staticBlock)){
    	$html .= '<span class="nav-static-block" style="background:#fff; border-top:1px solid #ccc; padding:10px;">';
    	$html .= $staticBlock;
    	$html .= '</span>';
    }
    $html .= '</ul>';
    

    The implementation is simple, check if there is a static block with the identifier value set to current category ID with a prefix “category-node-”. If so, add the static block to the menu. The prefix is used because if you inspect the value of $chlid->getId() you will see that it returns a category ID with that prefix so, for example, if the category ID is “10″ you will get “category-node-10″. I used this value because it is unique for each individual category.

    I used some inline CSS for the sake of simplicity but you should use your own.

  5. Now you need to create a static block with the identifier value set to whatever category Prefix+Category ID you want and you are all done! I used the default Magento sample data and created a static block with the identifier set to “category-node-10″ because Furniture category has the id of 10. That’s it.

Hope you’ll find this post helpful.

23
Top

Care to rate this post?

Author

Srdjan Stojiljkovic

Frontend Developer

Srdjan worked at Inchoo from October 2011 to September 2013. He was a Frontend Developer at Novi Sad, Serbia branch.

Other posts from this author

Discussion 23 Comments

Add Comment
  1. Does this work with the new navigation code in CE 1.7 ?

  2. Srdjan Stojiljkovic

    Thank you Johnboy for pointing that out. I updated the post to include a version that works in Magento 1.7

  3. No problem, the changes caught me out with a module I had been working. Took me a while to work out why the hell my extra menu item had dissappeared.

  4. Nice tutorial. Just what i needed for an customer project.

  5. Hey Srdjan… Congratulations for your 1st post… Keep them coming :)

  6. Neil

    Hey Srdjan,

    Great article. Do you know if it’s also possible to get the category id for each item in the navigation and to be able to add extra CSS classes for certain dropdowns to style them differently?

  7. Srdjan Stojiljkovic

    Yes you can get the category id for both versions (1.6 and 1.7). It’s just a little bit different.
    For Magento 1.6: $category->getId();
    For Magento 1.7: substr($child->getId(), strrpos($child->getId(), ‘-’) + 1);
    The thing is, in Magento 1.7 $child->getId() returns a string with the “category-node-” prefix (you get the following format “category-node-4″) so we need to extract the id from it by using some standard PHP sting functions.

    As for the CSS classes I added one (“nav-static-block”) for categories that have static blocks but you can use the category id from above to specify the class for every item in the menu which you can then style with CSS.

  8. Hi. Thanks for helpful information. Our team has described similar topic posted here http://www.atwix.com/magento/how-to-add-a-new-item-to-the-navigation-menu/ you are welcome to check it out and leave your feedback

  9. This is really awesome. I never that I can add static block to navigation also.

    THanks.

  10. First of all, Thank you so much for your posting.
    It’s really what I need. awesome!
    It could be added some images with static block.

    May I ask a favor of you?

    How can I move a static block to right side of the sub categories instead bottom side?

  11. person

    i did the same steps for magento 1.7 but for topmenu.php it still uses the con\re one & don’t over ride it how can i over ride it?

  12. Hi guys, this tutorial is awesome, got it working great except my nav won’t load the static blocks on the product pages. Works fine on home and category pages. Anyone else having this problem?

  13. Thanks for the tutorial, works great for adding in a graphic to the nav on a project that im working on.

    Just wondering if I could possibly get the block to be generated outside of the that is built?

  14. Marcus

    Dear Inchoo,

    thanks for this article. Im my case I want to replace the whole main navigation with a static block and I wonder where I can add this code: getLayout()->createBlock(‘cms/block’)->setBlockId(‘navigation’)->toHtml(); ?>. I also tried to add navigation to my page.xml but this does not work. Please help me…

    Best regards,
    Marcus

  15. Karthikeyan

    Hi ,

    Use this to remove p tags

    $html .= ”;
    $html .= $this->_getHtml($child, $childrenWrapClass);
    $staticBlock = trim($this->getLayout()->createBlock(‘cms/block’)->setBlockId($child->getId())->toHtml());
    if(!empty($staticBlock)){
    $html .= ”;
    $staticBlock =preg_replace(array(‘##’, ‘##’), ”, $staticBlock, 1);
    $html .= $staticBlock;
    $html .= ”;
    }
    $html .= ”;

  16. Karthikeyan

    Hi

    Add these lines in template/page/html/topmenu.phtml

    <a class="level-top" href="getUrl() ?>”>__(‘Home’) ?> <a href="getUrl(‘customer-service’) ?>” class=”">Customer Service

  17. Karthikeyan

    sorry i code’s were trimmed

  18. Rik

    If I use the standard template (default) it works great, but when I use my own template I don’t see a change when I edit the file app/code/local/Mage/Page/Block/Html/Topmenu.php . Can anyone help me?

  19. Michael

    I have same question aswell like Lucia had before. How can I move the static block to the right? I see no option to implement float:right anywhere in the code

    Lucia G.
    10-07-2012 at 20:03 | #

    First of all, Thank you so much for your posting.
    It’s really what I need. awesome!
    It could be added some images with static block.

    May I ask a favor of you?

    How can I move a static block to right side of the sub categories instead bottom side?

  20. Nik

    Hii… can you please help me for adding STATIC BLOCK in subcategories in navigation on mouse hover

  21. Nicholas Darley
  22. gt

    Nice tutorial, but one problem, the images are not https secured, which causes the page only partially secured. The Https Color bar is disappeared at secure pages, like login, my account, etc.

  23. Srdjan Stojiljkovic

    Regarding all the comments about floating the static block, this post is about functionality and how you can connect a category with a static block in the main navigation menu. Position and HTML structure of elements is not what I was aiming for because it depends on a particular design and template. On the other hand, it’s simple HTML and CSS which should not be a problem for a developer working in Magento.

Add Your Comment

Please wrap all source codes with [code][/code] tags.
Top