ErstwhileLayout is the base class for layouts. In Erstwhile, layouts are essentially the “frame” of the page, the part of the page that stays (generally) consistent as the user moves around the application. This can include the header, navigation, footer, and similar elements to that.
Layouts are implmented just like other ErstwhileComponents, but typically contain a lot of HTML boilerplate due to the nature how web pages are constructed. We call these “Fat Layouts;” Erstwhile lets you place a lot of this non-elegant code in one place and hide it behind a simple component with well-defined integration points in attributes to access its functionality.
For example, the Mazer theme has a ErstwhileLayout component called <FullLayout> that isn’t very pretty:
<%
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>Should you choose to include it within your application, though, you can consume it 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>
You can ignore the unsightly parts of the code and just work with the wrapper.
At this time, ErstwhileLayout doesn’t have any specific methods that can be overwritten. When creating layouts, you can denote the place you’d like to insert the page content with a <pagecontent /> tag.