Menus in Rails with simple-navigation and Bootstrap

Problem

Almost every application needs a menu (at least one). For simple menus it could be tempting the idea to write our menu helpers but if we have more than one menu or our menu is complex we could prefer to use something ready and well tested.

Additional problem

If we want to use the Twitter’s Bootstrap framework write the right markup with the right classes could be boring (and we know Rails programming is all about fun, right?)

Bootstrap dropdown menu

Solution

simple-navigation is a gem that gives us a simple DSL (Domain Specific Language) to define menus and an helper to render these menus in views.
Every menu is defined in a single file (DRY!) and with the simple-navigation-bootstrap gem we can even generate the markup for Bootstrap menus easily.

Installation

First of all we need to install the simple-navigation and simple-navigation-bootstrap gems (I’m assuming your application already loads the Bootstrap’s stylesheets and javascripts, if you don’t use bootstrap just install the simple-navigation gem).

Add the following line to your Gemfile:

# Gemfile
gem 'simple-navigation'
gem 'simple-navigation-bootstrap'

and install them:

$bundle install

Once installed you can run the generator to generate the default menu configuration:

$bundle exec rails g navigation_config

At this point restart your rails server if it’s running.

Menu configuration

Well, the generator write a navigation.rb file in your config directory, this is the file where all the magic happens.

The file is well documented but I suggest you to have a look at the simple-navigation wiki for more information.

SimpleNavigation::Configuration.run do |navigation|
  # Use Bootstrap renderer provided by the
  # simple-navigation-bootstrap gem
  navigation.renderer = SimpleNavigation::Renderer::Bootstrap

  # Item keys end up to be list items' IDs.
  # This setting avoids it
  navigation.autogenerate_item_ids = false

First of all we say to simple-navigation to use the Bootstrap renderer. A renderer is a class that build the HTML markup for us, in this case generate the markup needed by Bootstrap (You can remove this line if you don’t use Bootstrap).

The second thing I do here is to leave off the IDs from the menu markup because I don’t use them.

Now inside this block we can use the navigation variable to actually add navigation items to the menu:

# Define the primary navigation
navigation.items do |primary|
  # Bootstrap classes for tabbed menu
  primary.dom_class = "nav nav-tabs"

  primary.item :key_products, 'Products',
                              products_path,
                              :if => lambda { can? :index, Product }

  # User menu
  primary.item :key_1, 'User', '#' do |sub_nav|
    sub_nav.item :key_1_1, 'Profile', user_profile_path
    sub_nav.item :key_1_2, 'Logout', logout_path
  end
end

As you can see in the items block we first add some class to the navigation element (these are Bootstrap’s classes) and then add some menu item, in this case a “Products” item and a “User” item.
There are at least 3 interesting things to note here:

  1. In the “User” item we pass a block and define menu items inside the “User” second-level navigation.
  2. We pass a lambda to the :if option of the “Products” menu item. The menu item will be added only if the result is true, in this case I’m using the can? helper provided by the CanCan gem. Yes you have access to all your beloved helpers here ;)
  3. The Bootstrap renderer will add the right classes and markup for us.

At this point I’m sure you’re wondering how you can actually show the menu.

Show the menu

To show the menu you need to add a call to the render_navigation helper method provided by the simple-navigation gem.

For example a good place where to render your menu is in the layout:

<%= render_navigation(:expand_all => true) %>

The :expand_all option say to simple-navigation to put the submenu’s items even if not actives (without this option you’ll end up with empty submenus)

More than one menu?

As I said, simple navigation allow you to define more than one navigation, for example an administration menu to show only in a certain area of your application.

What you have to do is just create another file under /config, say config/another_navigation.rb, define your navigation there and then in your view add the following line:

<%= render_navigation(:context => :another, :expand_all => false) %>

Here you specify the context option which is the part before the “_navigation.rb” in the name of the menu configuration.

Conclusion

How we’ve seen add a navigation to our Rails application is not so hard, we don’t need to reinvent the wheel and write lines and lines of HTML markup paying attention to not forget some class in the process.

For more information you can read the good gems’ documentation but at this point you should be able to add (in few minutes) a navigation to your Rails application ;)

{lang: 'it'}


Puoi seguire le risposte a questo articolo tramite il feed RSS 2.0.
Puoi anche lasciare un commento, o creare un trackback dal tuo sito.

Non ci sono ancora commenti, puoi essere il primo, di' la tua!


Lascia un commento

XHTML: Puoi usare questi tag: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

*