Over a million developers have joined DZone.

Nested Layouts in HarpJS

· Java Zone

Learn more about the advantages of moving from a monolithic to microservices architecture.  Brought to you in partnership with IBM.

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

From Idea to Application gives you the architecture to quickly build, manage and run a range of applications (web, mobile, big data, new smart devices, etc.) on an open-standard, cloud-based platform. See why developers are using IBM Bluemix. Brought to you in partnership with IBM.


Published at DZone with permission of Raymond Camden, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}