Layout Pages, Content Pages, Partials and Sections

The Response.ExpandTemplate() and Response.ExpandScript() methods can render Partial and Layout pages. Partial pages allow creating nested pages of partial content that is pulled into the parent page. Layout pages allow you to create the base page layout in a single page that can be reused for many or all content pages. Layout pages then contain a Content region into which the content page is rendered as well as optional sections that can be used to render additional content from the content page into the Layout page. A content page references a Layout page and the layout page then renders the content page into it.

Scripts and Templates: Same Syntax

Scripts and Templates use the same basic syntax to describe Layout, Sections and Partials using specific tags that can be embedded into a script or template. Note that the markup syntax is finicky and you need to ensure you use the right amount of spacing and the right quote characters in order for these tags to work. This has been done to optimize performance in finding these tags at runtime. Please make sure you follow the layouts described below exactly.

For the following examples I'll use a script page (.wcs), but the syntax related to these concept is identical in both scripts and templates.

Content Page

Content pages are the pages that contain your main page content. When you create CustomerList.wcs or CustomerDetail.wcs the page that is referenced first and starts template/script execution is always the content page.

Content pages can either be totally self contained in which case they render a complete HTML document, or they can be a child page to a Layout Page which acts as a reusable master container that provides some common page layout that many Content pages can reuse.

Content Pages can also contain Partial Pages which are referenced scripts or templates, which are useful for breaking up complex pages into more manageable, smaller page fragments that are easier to work with.

Here's a self contained Content Page:

<html>
<head>
   <title>< %= pcTitle %>
</head>
<body>
   Hello < %= pcName %>, the time is <%= TIME() %>.
   <hr>
   <% for x=1 to 10 %>
       <%= "output" + TRANSFORM(x) %>
   <% endfor %>
</body>
</hml>

And here's a more complex Content Page that references a Layout page and pulls in content from a Partial page:

<% Layout="~/LayoutPage.wcs" %> 
<% section="headers" %>
     <title>My 3nd Awesome Web Page - <%= Time() %> </title>
     <link href="css/MyPage.css" rel="stylesheet" />
<% endsection %>  
 
<div>           
<h3>This is my CONTENT PAGE</h3>
<p>   
  Time is: <%= DateTime() %> Yup it is!   
</p>
  
<h3>Partial Content below (10x)</h3>  
<hr />  
<% for x = 1 to 5 %>     
    <%= RenderPartial("~/PartialPage.wcs") %>  
<% endfor %>
<hr />
    
           
</div>               
<% section="bottomcontent" %>
    Bottom Content:<br />
    <%= Version() %>
<% endsection %>
<% section="scripts" %>    
    <script src="bower_components/jquery/jquery.js"></script>
<% endsection %>

This page contains a Layout section, a Partial reference and a couple of Sections that allow injecting content into a Layout page from the Content Page.

Layout Pages

To reference a layout page from a Content page use the Layout property with a location for the Layout Page:

<% Layout="~/Views/LayoutPage.wcs" %>

Layout pages are top level pages that typically hold a common page frame - things like the page head (html,head,body tags) as well as the HTML for the banner, top level menu, as well as a footer. Most pages in a site use a common layout and a Layout page can provide most of that common layout on a single page.

An embedded <%= RenderContent() %> tag is then used to embed the actual Content page into the layout.

Here's a simple layout page:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>    
    <%= IIF(vartype(pcTitle) = "C",pcTitle,"") %>    
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link href="bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet" />
    <%= RenderSection("headers") %>
</head>
<body>    
    <%= RenderPartial("~/Views/Common/LoginTag.wcs") %>
   
    <h1>HEADER FROM LAYOUT PAGE</h1>         
    
    Content goes here:
    <%= RenderContent() %>    
    
    <hr />   
    LAYOUT FOOTER 
             
    <%= RenderSection("scripts") %>           
</body>  
</html>

This page contains a Content area, two sections and one partial:

Content Section
<%= RenderContent() %>

RenderContent() is the most important tag on a Layout Page: It's where the Content Page gets rendered. The content rendered is the initial page you requested as part of the render operation so CustomerList.wcs or CustomerDetail.wcs for example.

Sections

A layout page can define sections, which allow content pages to inject content into the Layout page. The reason for this is that the Layout page is a master page and the content page renders into a specific location inside of the Layout Page's content. If the Content Page needs to add content at the top or bottom of the page, there's no direct way of doing that.

Sections allow a way around this by providing injection points in the Layout Page where a Content Page can inject content.

The default layout page template has two pre-defined sections:

  • headers - Defined at the bottom of the <head> section
    Use this to inject additional page headers into the page. For example if you need to add meta tags or custom social media headers. You can also use this to add CSS Stylesheets or scripts that need to load BEFORE the stock script libraries

  • scripts - Defined at the bottom of the page after script library definitions
    Use this for injecting page specific JavaScript libraries and

and you can easily add others.

To define a section in a Layout Page use this syntax by providing a section label:

<%= RenderSection("scripts") %>

This creates an insertion point where section text from a content page can be rendered.

To declare section content that gets injected into the Layout Page from a Content Page:

<% section="scripts" %>
<script src="scripts/mypage.js"></script>
<script>
   // your javascript code here
</script>
<% endsection %>

This injects the result of the scripts section in the Content Page into the <%= RenderSection("scripts") %> location of the Layout page.

Section Content Expressions are Evaluated

Any expressions defined inside of a Section are always evaluated rather not executed, even if running inside of scripts. This means you can't use Codeblocks inside of sections nor access LOCAL variables or THIS points. Any variables referenced from scripts must be PRIVATE or PUBLIC.

Partial Pages

Partial pages are nested, child pages that are rendered from a content or layout page.

To reference a partial page embed the following:

<%= RenderPartial("~/Views/Common/LoginTag.wcs") %>

RenderPartial() embeds the content of another page into the current Content Page or Layout Page. You pass a Web site relative path starting with the ~ which signifies the site root path, followed by the path to the page you want to pull into the current page. The partial page is then executed as a script or template and the content injected into the page replacing the <%= RenderPartial() %> expression.

We've already seen partial pages called in the other examples. Partial pages are typically HTML fragments, not complete pages. A good example of a partial page might be the Login/Account Status section at the top of the page. You can create the partial once and re-use it in multiple pages.

<div class="login-widget">
    <% if poUser.IsAuthenticated %>
       <a href="profile.wcs"><%= poUser.Username %></a>
    <% else %>
       <a href="login.wcs">Login</a>
    <% endif %>
</div>

To use the partial you then simply reference the page where the script is stored from another script.

<%= RenderPartial("~/LoginWidget.wcs") %>

Partials are great for breaking up complex pages into smaller more manageable sub-pages as well as providing re-usability. For example, if you have a complex list display you might want to break the individual rows or even individual columns out to be rendered from a partial to make the HTML more readable.

Putting it all together

Building applications that use one or more Layout pages, with a number of Sections, and then using Content pages to create the actual content for pages in small self contained blocks, make HTML creation much more manageable. You don't have to copy and paste large blocks of common HTML into every page or render partial scripts into each page. Rather you let the Layout page handle the 'top level' layout of the page, with a few holes left to fill for the main RenderContent() and with Section directives to allow any content pages to fill in other common areas of the page.

Partials are useful to create reusable page components, or to break up large complex pages into smaller more manageable chunks.

Using all of these in combination makes it much easier to create complex applications and it's an effective workflow that minimizes repeated markup.


© West Wind Technologies, 1996-2018 • Updated: 08/14/17
Comment or report problem with topic