Layouts are specialized components that are subclasses of ErstwhileLayout. They are meant to serve as frames for your action templates, and typically include things like navigation, sidebars, headers, footers, and things like that. Quite often they will use Scoped Variables in the session scope to show things like user names or photos, or render navigation that’s present across multiple pages.
Fat Layouts
Erstwhile believes in getting things done in as little code as possible. It’s a fact that HTML is a fairly verbose markup language, particularly when it comes to things like navigation where you often need to use additional tags to move things around and position them correctly across different breakpoints. Here is where the concept of Fat Layouts comes in.
Using Mazer’s <FullLayout /> as an example, the code is pretty weighty:
<%
function renderSidebarMenuItem( menuItem, submenu = false ) {
%>
<li class="<%= (submenu ? "submenu-item" : "sidebar-item") %> <%= (menuItem.id && menuItem.id == args.sidebarMenuActive ? "active" : "") %> <%= (menuItem.children ? "has-sub" : "") %>" <%= (menuItem.id ? `id="sidebar-menu-${menuItem.id}"` : "") %>>
<a href="<%= (menuItem.link ? menuItem.link : "#") %>" class="<%= (submenu ? "submenu-link" : "sidebar-link") %>">
<% if(menuItem.biIcon) { %><i class="<%= `bi bi-${menuItem.biIcon}` %>"></i><% } %>
<span><%= (menuItem.label ? menuItem.label : "Item") %></span>
</a>
<% if(menuItem.children) { %>
<ul class="submenu">
<% for(let j in menuItem.children) {
renderSidebarMenuItem(menuItem.children[j], true);
} %>
</ul>
<% } %>
</li>
<%
}
%>
<div id="app">
<div id="sidebar">
<div class="sidebar-wrapper active">
<div class="sidebar-header position-relative">
<div class="d-flex justify-content-between align-items-center">
<div class="logo">
<a href="/"
><img
src="<%- (args.logo ? args.logo : "https://placeholder.pics/svg/500x200") %>"
alt="Logo"
srcset=""
/></a>
</div>
<div class="sidebar-toggler x">
<a href="#" class="sidebar-hide d-xl-none d-block"
><i class="bi bi-x bi-middle"></i
></a>
</div>
</div>
</div>
<div class="sidebar-menu">
<ul class="menu">
<% if(args.sidebarMenu && args.sidebarMenu.length > 0) { %>
<% for(let i in args.sidebarMenu) {
if(args.sidebarMenu[i].label) { %><li class="sidebar-title"><%= args.sidebarMenu[i].label %></li><% } %>
<%
for(let j = 0; j < args.sidebarMenu[i].items.length; j++) {
renderSidebarMenuItem(args.sidebarMenu[i].items[j]);
}
%>
<% }} %>
</ul>
</div>
</div>
</div>
<div id="main">
<header class="mb-3">
<a href="#" class="burger-btn d-block d-xl-none">
<i class="bi bi-justify fs-3"></i>
</a>
</header>
<div class="page-heading">
<div class="page-title">
<div class="row">
<div class="col-12 col-md-6 order-md-1 order-last">
<h3 id="page-title"><%- args.pageTitle %></h3>
<p id="page-intro" class="text-subtitle text-muted">
<%- args.pageIntro %>
</p>
</div>
<div class="col-12 col-md-6 order-md-2 order-first">
<nav
aria-label="breadcrumb"
class="breadcrumb-header float-start float-lg-end"
id="breadcrumb-container"
><% if(args.breadcrumbs) { %>
<ol class="breadcrumb">
<% for(let i in args.breadcrumbs) { %>
<li class="breadcrumb-item <%= (i == args.breadcrumbs.length - 1 ? 'active' : "") %>" <%= (i == args.breadcrumbs.length - 1 ? 'aria-current="page"' : "") %>>
<% if(args.breadcrumbs[i].link) { %>
<a href="<%- args.breadcrumbs[i].link %>"><%- args.breadcrumbs[i].label %></a>
<% } else { %>
<%- args.breadcrumbs[i].label %>
<% } %>
</li>
<% } %>
</ol>
<% } %>
</nav>
</div>
</div>
</div>
<pagecontent />
</div>
<footer>
<div class="footer clearfix mb-0 text-muted">
<div class="float-start">
<% if(args.copyrightYear || args.copyrightName) {%>
<p><%- args.copyrightYear %> © <%- args.copyrightName %></p>
<% } %>
</div>
<div class="float-end">
<% if (args.footerMessage) { %>
<p>
<%- args.footerMessage %>
</p>
<% } %>
</div>
</div>
</footer>
</div>
</div>We call this a Fat Layout because it contains a bunch of code you don’t want to have to look at every day. You want to figure it out once and then stick it in a library somewhere to not have to think about again.
By sticking it in an Erstwhile component, the application can have a layout (under /app/views/layouts/full.ejs, for example) that looks like this:
<FullLayout logo="/assets/images/todos-logo.png" sidebarMenu="@.session.sidebarMenu" sidebarMenuActive="@.page.sidebarMenuActive" breadcrumbs="@.page.breadcrumbs" copyrightYear="<%= (new Date()).getFullYear() %>" copyrightName="<a class='external' target='_blank' href='https://www.restlessdev.com'>RestlessDev</a>" footerMessage="Made with <span class='text-danger'><i class='bi bi-heart-fill icon-mid'></i></span> in New Orleans" pageTitle="@.page.title" pageIntro="@.page.intro" appName="Todos" meta="@.page.meta" > <pagecontent /> </FullLayout>
Your application is now only concerned with the data that needs to get to the layout and not all of the unsightly markup. It’s a cabbage soup diet for your code.