Skip to content
andi edited this page Sep 13, 2010 · 18 revisions

By default your navigation is configured in the file config/navigation.rb. To generate a template-file with comments in it (to have an easier start), call the following generator:

$ script/generate navigation_config

In the config/navigation.rb file you define your navigation items as illustrated in the following example:

SimpleNavigation::Configuration.run do |navigation|  
  navigation.items do |primary|
    primary.item :books, 'Books', books_path
    primary.item :music, 'Music', musics_path
    primary.item :dvds, 'Dvds', dvds_path
  end
end

This creates a primary navigation with three items (for an online store which sells books, music and dvds). For each item, you define

  • a key (used for identifying the active navigation item in the controllers)
  • a name (string or a call to your I18n framework)
  • the url that the item points to (you can use url_for, restful routes helper, named route helpers or any url as string)
  • optionally you can add html-options that are passed on to the rendered navigation items (e.g. class, id etc.)

If you want to define a sub navigation for a primary item you can specify a block for that item, e.g.

primary.item :books, 'Books', books_path do |books|
  books.item :fiction, 'Fiction', fiction_books_path
  books.item :history, 'History', history_books_path
  books.item :sports, 'Sports', sports_books_path
end

which defines three sub navigation items for ‘Books’.

You can nest as many sub navigations as you like, i.e. if you would like to add a sub navigation for ‘History’, simply add another block to that item:

...
books.item :history, 'History', history_books_path do |history|
  history.item :ancient, 'Ancient', ancient_books_path
  history.item :modern, 'Modern', modern_books_path
end
...

Availability of Helpers inside the Config File

The config file is evaluated in the context of the view that renders the navigation. This means you can access all the view-helpers inside the config-file.

Conditional Navigation Items

If you want a navigation item to appear only if certain conditions apply (e.g. only showing an item linking to the admin-zone if the user is admin), you can use :if or :unless options specifying a proc (or lambda) that contains your condition:

primary.item :admin, 'Admin', admin_path, :if => Proc.new { current_user.admin? }

or if you want to show an item only if a user is logged in:

primary.item :account, 'Account', account_path(@user), :unless => Proc.new { logged_in? }

The procs you specify are – as stated above – evaluated in the context of the views, thus you can use all the methods and vars in your proc that are available in the views.

Restful delete links

If you need a navigation item that performs a destroy action (restfully spoken), you can specify :method => :delete as an option for your navigation item:

primary.item :logout, 'logout', session_path, :method => :delete, :if => Proc.new { logged_in? }

For further information on the config/navigation.rb file (more options etc…) check the comments in the generated file itself.

Highlighting the active Navigation Item

Once you have defined your navigation you may ask yourself how to mark a specific navigation item as selected (ie. highlighted). There are basically three circumstances which can mark a navigation item as selected:

  • Automatic highlighting – Since version 2 there is a feature called ‘auto highlighting’ which is turned on by default. With auto highlighting turned on the url that has been defined for the navigation item (in the config file) is matched against the current request’s url. If there is a match, the item is marked as selected.
  • Explicit highlighting in the controllers – In the controllers you can explicitly configure which items are highlighted.
  • Sub navigation is selected – If you have more than one level of navigation and a sub navigation of an item is selected, that item (i.e. the parent) also gets marked as selected.

Automatic Highlighting

As described above with automatic highlighting enabled a navigation item is marked as selected if its url matches the current request’s url. This probably works for about 80% of the use cases. That’s why it’s turned on by default. However, depending on your application and navigation setup you might encounter two categories of problems:

An item that you think should be auto highlighted is not

This situation might occur for

  • urls with dynamic params, e.g. if you are displaying a paged list with the current offset as param and the highlighted navigation item should be the same for the whole paging process
  • incomplete navigations, e.g. you have defined a top level navigation (e.g. Account) that actually has sub pages (e.g. User Data, Settings) but you don’t have a sub navigation that stands for these sub pages. In that case you probably want the top level navigation to be highlighted for all the sub pages, thus auto highlighting cannot help here.

The solution for those kinds of problems is to explicitly define the active navigation items in the corresponding controllers (see below).

An item should not be auto highlighted but nonetheless is

This situation should rarely occur. If it does you can always disable the automatic highlighting feature either globally or for a specific navigation level.

To disable it globally for the whole plugin, set

SimpleNavigation::Configuration.run do |navigation|  
  navigation.auto_highlight = false
  navigation.items do |primary|
  ...
  end
end

To turn it off for specific level (e.g. the primary navigation), set

SimpleNavigation::Configuration.run do |navigation|  
  navigation.items do |primary|
    primary.auto_highlight = false
    ...
  end
end

There might be other cases where auto highlighting doesn’t work. Please drop me a line if you experience such problems.

Explicit Highlighting in the Controllers

There are two methods available in the controllers to explicitly set the active navigation.

First, there’s the class method navigation that sets the active navigation for all actions of a controller. For example, if you have a BooksController and you want the ‘Books’ primary navigation item to be explicitly active for all action of that controller, just call

class BooksController < ApplicationController
  navigation :books
  #your actions here
end

Or if you have a sub navigation and a controller which handles the subcategory of books, then you specify:

class BooksFictionController < ApplicationController
  navigation :fiction
  #your actions here
end

which activates the ‘Book’ primary navigation (since it’s the parent of ‘Fiction’) and displays its sub navigation (‘Fiction’, ‘History’, ‘Sports’) with the ‘Fiction’ item as being active.

Please note here that :fiction is a sub navigation item of :books. If you set the navigation to :fiction, :books is automatically highlighted, too.

The second way to specify the active navigation is to call current_navigation inside your actions, e.g.

class BooksController < ApplicationController
  navigation :books

  #not really restful
  def show_recommended_dvds
    #...
    current_navigation :dvds
  end

end

Calling current_navigation in an action overrides the active navigation you have set with the class method navigation.

Clone this wiki locally