Nested Layouts in HarpJS

This post is more than 2 years old.

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>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="description" content="">
<meta name="viewport" content="width=device-width">

	<%- yield %> 

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.

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA

Archived Comments

Comment 1 by RhinoMaster posted on 3/1/2014 at 1:41 AM

Interesting, this approach reminds me of apply-templates from XSLT.

Comment 2 by Raymond Camden posted on 3/1/2014 at 1:42 AM

Is that good or bad? :) I've only played with XSLT a bit. I found them powerful, but not necessarily friendly.

Comment 3 by RhinoMaster posted on 3/1/2014 at 4:08 AM

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 -

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.

Comment 4 by Raymond Camden posted on 3/1/2014 at 9:15 PM

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.