This website stores cookies on your computer. These cookies are used to collect information about how you interact with the website and allows us to remember you. We use this information in order to improve and customize your browsing experience and for analytics and metrics about visitors to this website. If you decline, your information won’t be tracked when you visit this website. A single cookie will be used in your browser to remember your preference not to be tracked.
Blog > Middleman Partials > Partials

Partials

So far I haven't taken full advantage of templating in Middleman. I should be able to create components as partials that I can embed in the site at different points. This keeps the site DRY and changing one component can have an impact on multiple pages.

As this is my first attempt I am going to start small. Using the blog template, which you can see in the second article of the blog, as my starting point I am going to turn the navigation <aside> into a partial.

Here is the layout.erb that you get out of the box when you use the Middleman blog template.

<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta http-equiv='X-UA-Compatible' content='IE=edge;chrome=1' />
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Blog Title<%= ' - ' + current_article.title unless current_article.nil? %></title>
    <%= feed_tag :atom, "#{blog.options.prefix.to_s}/feed.xml", title: "Atom Feed" %>
  </head>
  <body>

    <div id="main" role="main">
      <%= yield %>
    </div>

    <aside>
      <h2>Recent Articles</h2>
      <ol>
        <% blog.articles[0...10].each do |article| %>
          <li><%= link_to article.title, article %> <span><%= article.date.strftime('%b %e') %></span></li>
        <% end %>
      </ol>

      <h2>Tags</h2>
      <ol>
        <% blog.tags.each do |tag, articles| %>
          <li><%= link_to "#{tag} (#{articles.size})", tag_path(tag) %></li>
        <% end %>
      </ol>

      <h2>By Year</h2>
      <ol>
        <% blog.articles.group_by {|a| a.date.year }.each do |year, articles| %>
          <li><%= link_to "#{year} (#{articles.size})", blog_year_path(year) %></li>
        <% end %>
      </ol>
    </aside>
  </body>
</html>

I will create a new directory under source called partials and then create a file called _blog_nav.erb. The <aside> block from the layout needs to be moved into the new file.

mkdir  ~/middleman_blog_project
cd ~/middleman_blog_project
middleman init --template=blog

mkdir ~/middleman_blog_project/source/partials
vi ~/middleman_blog_project/source/partials _blog_nav.erb #insert the content via the vi command or your choice of editor

The layout.erb will now look like

<!doctype html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta http-equiv='X-UA-Compatible' content='IE=edge;chrome=1' />
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Blog Title<%= ' - ' + current_article.title unless current_article.nil? %></title>
    <%= feed_tag :atom, "#{blog.options.prefix.to_s}/feed.xml", title: "Atom Feed" %>
  </head>
  <body>

    <main>
      <%= yield %>
    </main>

    <%= partial "partials/blog_nav" %>

  </body>
</html>

Notice that I have amended the <div> tag with the id of main to be a <main> tag. This makes sense in this case as it is the main content of the page.

~/middleman_blog_project/source/partials/_blog_nav.erb will need the content

<aside>
  <h2>Recent Articles</h2>
  <ol>
    <% blog.articles[0...10].each do |article| %>
      <li><%= link_to article.title, article %> <span><%= article.date.strftime('%b %e') %></span></li>
    <% end %>
  </ol>

  <h2>Tags</h2>
  <ol>
    <% blog.tags.each do |tag, articles| %>
      <li><%= link_to "#{tag} (#{articles.size})", tag_path(tag) %></li>
    <% end %>
  </ol>

  <h2>By Year</h2>
  <ol>
    <% blog.articles.group_by {|a| a.date.year }.each do |year, articles| %>
      <li><%= link_to "#{year} (#{articles.size})", blog_year_path(year) %></li>
    <% end %>
  </ol>
</aside>

Conditionally Render the Partial

This can now be taken further, perhaps by making the partial only render under certain conditions. Perhaps some of your blog pages have the frontmatter tag of nav: true. We then add the condition to the layout.erb

...

<% if defined?(current_page.data.nav) %>
  <%= partial "partials/blog_nav" %>
<% else %>
...

Note that this is just looking for the presence of the attribute not the attribute value. You could also have something like

...

<% if current_page.data.nav %>
  <%= partial "partials/blog_nav" %>
<% else %>
...

I now just need to leverage partials throughout the site.