Twitter: raymondcamden


Address: Lafayette, LA, USA

Nested Layouts in HarpJS

02-27-2014 3,810 views Development, HTML5 4 Comments

Currently it isn't possible to use nested layouts in HarpJS. But with a little work you can support it easily enough. Here is a solution (with an alternative) that you can use until (if) HarpJS supports it natively in the future.

First, a reminder. By default, if you have a _layout.ejs (or .md, or that other template engine) in your folder, Harp will take the content of your current page and send it to the layout script as a variable, yield. So a simple layout could look like this:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title></title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
</head>
<body>

	<%- yield %> 
	
</body>
</html>

If you have a subdirectory, it can also specify a _layout.ejs file. When Harp encounters this file, it runs that layout instead of one higher in the directory structure. While you have the option to select a different layout template (in data.json) or ask for no layout, you can't have wrapped layout - i.e., use the current layout and then send the result to the parent layout.

This can solved by simply using partials in your layout file. These partials can then be loaded by other layout scripts. So imagine this as your main site layout.

<%- partial("_main_header") %>

<%- yield %>

<%- partial("_main_footer") %>

All I've done is taken the code that would have normally been above and below the yield statement and moved them into a partial. Now imagine I've got an articles folder with its own layout. I want to include the main site layout as well. This is all I do:

<%- partial("../_main_header") %>

<h3>Article Header</h3>

<%- yield %>

<h3>Article Footer</h3>

<%- partial("../_main_footer") %>

Boom. That's it. This works, but the more I use Harp, the more I become concerned with creating nice, maintainable scripts. I've noticed that many themes (including the one on my blog), suffer from "Div-Itis". You all know what Div-Itis is. You view source on a page and see approximately 30 different layers of div tags. I cant tell you how many times I've accidentally broken a layout because I screwed this up. I also can't tell you how many times I've said, "Screw it, let me add a closing div tag" in an attempt to fix something.

The solution above works, but separates my layout into two files (ok, technically three, but I'd never update the main layout again), so I wondered if it could be done better. I came up with another solution that uses the ability to pass variables to partials. Remember, partials in Harp are more than just include. You can pass data to them and they can react accordingly. I'm going to use a trick I've used for over a decade now when building ColdFusion templates.

<%- partial("_main", {mode:"header"}) %>

<%- yield %>

<%- partial("_main", {mode:"footer"}) %>

I've made a new partial, called main, and I pass a mode value to it. Now let's look at main.ejs.

<% if(mode === "header") { %>

<h1>MAIN HEADER</h1>

<% } else { %>

<h2>MAIN FOOTER</h2>

<% } %>

As you can see, I've simply added an IF clause that selects which branch of my layout to render. I've got some code intertwined in there, but at least I can look at the entirety of the template all at once.

I've included both demos as an attachment.

Download attached file

4 Comments

  • RhinoMaster #
    Commented on 02-28-2014 at 2:41 PM
    Interesting, this approach reminds me of apply-templates from XSLT.
  • Commented on 02-28-2014 at 2:42 PM
    Is that good or bad? :) I've only played with XSLT a bit. I found them powerful, but not necessarily friendly.
  • RhinoMaster #
    Commented on 02-28-2014 at 5:08 PM
    It's a good thing!

    As the name suggests, XSLT is a powerful templating language, but has some drawbacks, of which the likes of jade,ejs,haml etc address.

    By separating partials into templates and applying different modes, you can build quite a powerful, modular and reusable system - as long as one can conceptually keep up with it. ut this was also part of XSLT's problem (different concepts).

    As an example, have a look at some code I wrote a while back which transformed the shape of an XML document into a different structure. In particular, the way modes are applied - https://gist.github.com/Demwunz/4469400#file-maste...

    It will be interesting to see how HarpJS progresses with more complex structures, I think there is a lesson to be learnt from XSLT. Either way, I'm enjoying Harp immensely so far, and your own experience with it too.
  • Commented on 03-01-2014 at 10:15 AM
    Cool example there, and glad you are liking the demos so far. Speaking of templating, in theory, Harp will soon support Handlebars and I'm really looking forward to that.

Post Reply

Please refrain from posting large blocks of code as a comment. Use Pastebin or Gists instead. Text wrapped in asterisks (*) will be bold and text wrapped in underscores (_) will be italicized.

Leave this field empty