Using code to write HTML markup is tedious so in this article we convert the markup code in the Bed Nap application into efan templates and introduce the concept of components.

Writing out large amounts of HTML with multiline strings or WebOutStream is pretty awkward. It's difficult for designers to edit and you can't just cut'n'paste examples from the web. In general, it's pretty yukky. And so far we only have bare bones HTML and that code it's already a major part of our application!

It's time to switch to templating. We're going to use Embedded Fantom, or efan for short. Like JSP for Java and ERB for Ruby, efan turns our code inside out. While normal code has strings embedded within code, efan has code embedded within strings!

Index Page Template

To make the transition easy, we'll isolate the code that's going to be converted into an efan template. That involves moving it to a static method with a single parameter called ctx and having it return a Str.

And again, all out tests should still pass, because technically we've not changed the output of our application.

Note that at this point we can remove web from our list of dependencies for it was only required to access WebOutStream.

Use efan Templates

The efan docs say it's bad to constantly use the Efan.renderXXX() methods because over time they could eventually cause a memory leak. (Each call to render dynamically creates a Fantom type.) As we call Efan.renderXXX() every time a page is viewed, this is probably a bad thing!

So instead we will create EfanTemplateMeta instances and call render() on those.

The .efan files stay the same, we just update the code. IndexPage first:

It's nice... but basic. And the footer would always need to stay in sync with the header. For example, if the header opened up an extra <div> tag then the footer would need to be updated to close it.

So what if we turned this inside out. Rather than having pages that render components, we had a component that rendered pages!?

In pseudo code, our component template would look like:

render header stuff
pageTemplate.render()
render footer stuff

This is good... but hold that thought! Before we go any further, let's talk about...

Nested Templates

Nested templates is an efan term.

I best understand the concept in terms of HTML / XML... Let's assume we had an arbitrary <template> tag that represented some generic markup. We could potentially render it in a page like this:

<html>
...
<template />
...
</html>

If our generic markup was <div class="big bold">Hello Mum!</div> then when the page was rendered it would look like:

<html>
...
<div class="big bold">Hello Mum!</div>
...
</html>

But what if we wanted Hello Dad! to be big and bold, or some other text? Then ideally we would write:

<html>
...
<template>
Hello Dad!
</template>
...
</html>

Which would get rendered as:

<html>
...
<div class="big bold">
Hello Dad!
</div>
...
</html>

That Hello Dad! text is in effect the body of the template tag. And that body could be anything - even more tags and / or templates! If the body is passed into template, then the template could choose where in it's markup to render it.

And that is how nested efan templates work. If our fictional template was an actual Template.efan file it would look like this:

<div class="big bold"><%= renderBody() %></div>

renderBody() is a special method on an EfanTemplate that does just that.

See how the body is actually passed into the render() method as an it-block function.

Layout Component

Going back to rendering headers and footers, we are going to create an efan nested component (called LayoutComponent) that encompasses the header and footer of our pages. Using a Layout component is a common pattern.

We'll dive straight in a write what we want our LayoutComponent.efan to look like:

Being able to nest templates in this manner is an important and powerful concept.

Make your Ruby friends envious!

Ruby's ERB templating also has the notion of embedded templates. But only the top level template can render a body, hence they call it nested layout. efan takes the concept further and allows any template to render its body.

While nested components are powerful, there's still some work involved with parsing templates and setting up the ctx variables. That's where efanXtra comes in - efanXtra makes component templating much, much easier! See the next tutorial chapter to learn about efanXtra.