Navigations from Searches

Automatically generated navigations on a website are often based on a parent node and its children. With Scrivito, obtaining the list of children of a particular CMS object and iterating over them to render a navigation is rather straightforward.

But there are other use cases such as category-based or hand-picked navigation items. In these cases, the individual pages to show up in the navigation are widely spread over the object hierarchy, they're not children of a particular CMS object.

You could put the items into a reference list of a prominent page, e.g. the homepage. To render the navigation, the correspondig view would have to access this page and its list directly. This can be cumbersome for editors to work with.

A much better approach is to flag the pages that are to appear in the navigation, and use a search to find them. This way, an editor can set and remove the flag by means of the properties dialog of a page.

A simple footer navigation

We're going to proceed as follows to implement a search-based footer navigation whose items can be selected individually on the corresponding pages.

  1. For flagging the pages to show up in our navigation, a custom attribute is required. We'll name it “show_in_footer” and add it to every object class a page appearing in the navigation might have. For simplicity, we'll make it a string type attribute.
  2. We'll make this attribute editable in the properties dialog of the pages. Setting the attribute value to anything that starts with a “y” should make the page a navigation item.
  3. In the footer template, a search query is used to find the flagged pages and render the links pointing to them.

Adding the flag attribute

To add the “show_in_footer” attribute to a page type, just edit its model file and define the attribute, like so:

Copy
# app/models/content_page.rb
class ContentPage < Obj
  # …
  attribute :show_in_footer, :string
end

Making the attribute editable

For giving editors the possibility to change the value of an attribute on the page properties dialog, add the attribute to the “details.html.erb” view of the object class this attribute belongs to:

Copy
<!-- app/views/content_page/details.html.erb -->
<div>

  <h4>Headline</h4>
  <%= scrivito_tag(:div, @obj, :headline) %>

  <h4>Show in footer</h4>
  <%= scrivito_tag(:div, @obj, :show_in_footer) %>

</div>

As you can see, we use the “scrivito_tag” helper to display the attribute value and automatically make it changeable if in-place editing is switched on. This can be tested in place:

Rendering the footer navigation

First, we're going to implement a little helper that searches the flagged pages and renders links pointing to them. Then, we'll call this helper from within the layout.

Copy
# app/helpers/footer_nav_helper.rb
module FooterNavHelper
  def footer_nav
    items = Obj.where(:show_in_footer, :contains_prefix, 'y')
    content_tag(:ul, class: 'list-inline') do
      items.collect do |item|
          concat(content_tag(:li, link_to(item[:headline], scrivito_path(item))))
      end
    end
  end
end

The helper searches for CMS objects whose “show_in_footer” attribute value starts with “y”. Then, for each of them, the contents of their headline attribute is linked to the respective CMS object.

All that's left to do now is to call this helper from within the layout:

Copy
<!-- app/views/layouts/application.html.erb -->
<div class="footer">
…
  <%= footer_nav %>
…
</div>
Just add one or two “ContentPage”s to your site and flag them. You should then see the links to them in the footer.