This chapter presents information on how templates and wrappers are typically used when implementing websites.
This chapter contains the following sections:
In this section, we examine the difference between the three types of templates and their practical use in actual implementations.
A layout template is a template asset where the Usage field is set to Element is used as a layout. A layout template can be typed or typeless (see Section 23.4, "Creating Template Assets" for details on typed versus typeless asset).
A layout template has three main characteristics:
This section provides details for each of these characteristics and presents use-case scenarios that we will use across multiple sections to demonstrate various concepts. This section also presents Use Case 1: Building a Layout Template for Article Assets.
Given a layout template's pagename, a web page is obtained by calling the Satellite servlet and passing the pagename along with the asset type (c) and asset id (cid) of the content to render:
http://localhost:8080/cs/Satellite?pagename= <template_pagename>&c=Article&cid=1234567
The pagename corresponding to any given template can be found by inspecting a template asset and looking at the SiteCatalog Pagename column in the Site Entries field. In the screen capture below, the pagename is avisports/HelloLayout.
Every content asset has template metadata which is viewable by selecting the Content tab. This field stores a template name, the possible values include all layout templates applicable to the asset type and subtype.
How does WebCenter Sites use the template field? Basically, when inspecting or editing an asset in Web Mode of the Contributor interface, WebCenter Sites uses the assigned layout template as the default template to render the asset (this is also the case when simply previewing an asset). In practice, this means that only layout templates can be used to work with assets in Web Mode. Note that previewing does not require a layout template. See Section 23.7.5, "Previewing Template, CSElement, and SiteEntry Assets" for more information.
When working in Web Mode, the default layout template can also be assigned by using the Change Layout functionality (either from the toolbar or menu bar), and selecting a layout template visually, using the template picker. In either case, the value of the asset's template field is modified.
A standard web page is built with HTML code using <DIV> elements to define divisions within the document, typically a header, footer, side bar, and main area as shown in the diagram below.
The HTML structure used by the avisports sample site is used in the example below of a standard web page with a header, footer, side bar, and main area.
<!DOCTYPE html> <html> <head> </head> <body class="inner"> <div id="main"> <div id="header"> <!--contains the top menu bar --> </div> <div id="container"> <div class="content"> <!--contains the main area --> </div> <div class="side-bar"> <!--contains the side nav bar --> </div> </div> <div id="footer"> <!--contains the footer --> </div> </div> </body> </html>
An actual JSP page would include tag library directives, an opening and closing <cs:ftcs>
tag, and the <render:logdep>
tag, used by the cache manager. See Chapter 4, "Programming with Oracle WebCenter Sites" for more information.
<%@ taglib prefix="cs" uri="futuretense_cs/ftcs1_0.tld" %> <%@ taglib prefix="render" uri="futuretense_cs/render.tld" %> <cs:ftcs> <!DOCTYPE html> <% // The render:logdep tag is mandatory. It allows the cache manager // to automatically flush any page/pagelet generated using this // template ("tid" is automatically populated with the Template // asset id) %> <render:logdep cid='<%=ics.GetVar("tid")%>' c="Template" /> <html> <head> </head> <body class="inner"> <div id="main"> <div id="header"> <!--contains the top menu bar --> </div> <div id="container"> <div class="content"> <!--contains the main area --> </div> <div class="side-bar"> <!--contains the side nav bar --> </div> </div> <div id="footer"> <!--contains the footer --> </div> </div> </body> </html> </cs:ftcs>
The document must be enclosed within <cs:ftcs>
tags. This tag creates the WebCenter Sites context, alerting WebCenter Sites that code contained within the opening and closing <cs:ftcs>
tags will contain WebCenter Sites tags. WebCenter Sites is unaware of any code which falls outside of these tags. See Section 4.5, "WebCenter Sites Tags" for more information on the <cs:ftcs>
and <render:logdep>
tags.
In this section we define a layout template for article assets.
Using Eclipse with the WebCenter Sites Developer Tools plug-in, create a new template in the avisports sample site with these characteristics:
Site: avisports
Name: HelloArticleLayout
Asset Type: AVIArticle
Subtype: Article
Element Usage: Element is used as a Layout.
Element Type: JSP
Root Element: AVIArticle/HelloArticleLayout
Storage Path: AVIArticle/HelloArticleLayout.jsp
Use the following JSP code.
Note that we are reusing some of the components already written for avisports in order to render the standard avisports header and footer, and head section, which allows us to import the avisports stylesheets:
<%@ taglib prefix="cs" uri="futuretense_cs/ftcs1_0.tld" %> <%@ taglib prefix="render" uri="futuretense_cs/render.tld" %> <cs:ftcs> <!DOCTYPE html> <render:logdep cid='<%=ics.GetVar("tid")%>' c="Template" /> <html> <head> <!--inserts the standard avisports head --> <render:calltemplate tname="/Head" args="c,cid" style="element" /> </head> <body class="inner"> <div id="main"> <div id="header"> <!--inserts the avisports navbar --> <render:satellitepage pagename="avisports/navbar" /> </div> <div id="container" style="height: 350px"> <div class="content"> <!--contains the main area --> </div> <div class="side-bar" style="height: 300px"> <!--contains the side nav bar --> </div> </div> <div id="footer"> <!--inserts the avisports footer --> <render:callelement elementname="avisports/footer" /> </div> </div> </body> </html> </cs:ftcs>
Open any article asset in a new tab.
Assign the HelloArticleLayout template to the asset. You should get a web page like the following:
Note that we added some temporary style to the container and side-bar <DIV> elements so they are visible. We will remove them when those contain actual content.
Add code to the layout template so it renders actual content. This code renders the headline, post date, related image and body fields. See Chapter 11, "Data Design: The Asset Models" for information on attribute values.
<%@ taglib prefix="cs" uri="futuretense_cs/ftcs1_0.tld"%> <%@ taglib prefix="ics" uri="futuretense_cs/ics.tld"%> <%@ taglib prefix="render" uri="futuretense_cs/render.tld"%> <%@ taglib prefix="assetset" uri="futuretense_cs/assetset.tld"%> <%@ taglib prefix="dateformat" uri="futuretense_cs/dateformat.tld"%> <cs:ftcs> <!DOCTYPE html> <render:logdep cid='<%=ics.GetVar("tid")%>' c="Template"/> <% // load article content %> <assetset:setasset name="article" type='<%=ics.GetVar("c") %>' id='<%=ics.GetVar("cid") %>' /> <% // fetch the headline, relatedImage, and postDate attributes // from the database %> <assetset:getmultiplevalues name="article" prefix="article"> <assetset:sortlistentry attributename="headline" attributetypename="ContentAttribute" /> <assetset:sortlistentry attributename="relatedImage" attributetypename="ContentAttribute" /> <assetset:sortlistentry attributename="postDate" attributetypename="ContentAttribute" /> </assetset:getmultiplevalues> <% // fetch the body attribute // body has to be fetched separately, since it is a 'text' // attribute, and the getmultiplevalues tag does not support // 'text' attributes %> <assetset:getattributevalues name="article" listvarname="bodyList" attribute="body" typename="ContentAttribute" /> <% // read the related AVIImage asset id %> <ics:listget listname="article:relatedImage" fieldname="value" output="imageId" /> <% // read the date value and format it %> <ics:listget listname="article:postDate" fieldname="value" output="postDate" /> <dateformat:create name="df" datestyle="long" /> <dateformat:getdate name="df" varname="formattedDate" valuetype="jdbcdate" value='<%=ics.GetVar("postDate") %>' /> <html> <head> <!--inserts the standard avisports head --> <render:calltemplate tname="/Head" args="c,cid" style="element" /> </head> <body class="inner"> <div id="main"> <div id="header"> <render:satellitepage pagename="avisports/navbar" /> </div> <div id="container"> <div class="content"> <div class="top-section section-title"> <h1> <ics:listget listname="article:headline" fieldname="value" /> </h1> <span class="date"> <ics:getvar name="formattedDate" /> </span> </div> <div class="article post"> <render:getbloburl outstr="imageURL" c="AVIImage" cid='<%=ics.GetVar("imageId")%>' field="largeThumbnail" /> <img class="photo left" src='<%=ics.GetVar("imageURL")%>' /> <render:stream list="bodyList" column="value" /> </div> </div> <div class="side-bar" style="height: 300px"> <!--contains the side nav bar --> </div> </div> <div id="footer"> <render:callelement elementname="avisports/footer" /> </div> </div> </body> </html> </cs:ftcs>
Viewing our asset in Web Mode of the Contributor interface, using HelloArticleLayout, should render a web page with the article detail as shown below. Note that the side bar is intentionally empty.
A pagelet template is a template asset for which the Usage field is set to Element is used within an HTML page.
A pagelet template has the following characteristics:
In the following section, we detail each characteristic and continue enhancing our use-case example. This section also presents Use Case 2: Using Pagelet Templates.
Although a pagelet template has a pagename, attempting to access a pagelet template directly from a browser using a WCS URL will return a 403 HTTP error code (forbidden).
Only layout templates are available in the asset's template field. This means that, these assets cannot be directly previewed using a pagelet template. However, it is possible to set up preview templates, that would give editorial users a simple way to preview pagelet templates (see Section 24.1.3, "Page Templates" for more information).
A page template renders a web page fragment, not an entire web page. Ideally, a pagelet template represents a reusable page fragment. For instance, a pagelet template could render an article summary block such as the following:
Layout templates can then be used to assemble multiple page fragments in order to produce a complete web page. In order to maximize reusability, pagelet templates should provide neutral fragments from a look and feel point of view, with CSS stylesheet rules effectively controlling the visual result (based on where a given fragment is used, it would render differently, only by applying a distinct set of stylesheet rules).
See Section 24.1.1.4, "Use Case 1: Building a Layout Template for Article Assets" for previous steps.
If the code rendering the article detail is meant to be reused in multiple context, it makes sense to extract the code from the layout template, and turn it into a pagelet template.
Let's create the corresponding template asset with the following characteristics:
Using Eclipse with the WebCenter Sites Developer Tools plug-in, create the corresponding template in the avisports sample site with these characteristics:
Site: avisports
Name: HelloDetail
Asset Type: AVIArticle
Subtype: Article
Element Usage: Element is used within an HTML page.
Element Type: JSP
Root Element: AVIArticle/HelloDetail
Storage Path: AVIArticle/HelloDetail.jsp
Let's extract the code responsible for looking up and rendering the article field values inside the <div class="content">
element and turn it into a separate JSP:
<%@ taglib prefix="cs" uri="futuretense_cs/ftcs1_0.tld"%> <%@ taglib prefix="assetset" uri="futuretense_cs/assetset.tld"%> <%@ taglib prefix="ics" uri="futuretense_cs/ics.tld"%> <%@ taglib prefix="render" uri="futuretense_cs/render.tld"%> <%@ taglib prefix="dateformat" uri="futuretense_cs/dateformat.tld"%> <cs:ftcs> <render:logdep cid='<%=ics.GetVar("tid")%>' c="Template" /> <assetset:setasset name="article" type='<%=ics.GetVar("c") %>' id='<%=ics.GetVar("cid") %>' /> <assetset:getmultiplevalues name="article" prefix="article"> <assetset:sortlistentry attributename="headline" attributetypename="ContentAttribute" /> <assetset:sortlistentry attributename="relatedImage" attributetypename="ContentAttribute" /> <assetset:sortlistentry attributename="postDate" attributetypename="ContentAttribute" /> </assetset:getmultiplevalues> <assetset:getattributevalues name="article" listvarname="bodyList" attribute="body" typename="ContentAttribute" /> <ics:listget listname="article:relatedImage" fieldname="value" output="imageId" /> <ics:listget listname="article:postDate" fieldname="value" output="postDate" /> <dateformat:create name="df" datestyle="long" /> <dateformat:getdate name="df" varname="formattedDate" valuetype="jdbcdate" value='<%=ics.GetVar("postDate") %>' /> <div class="top-section section-title"> <h1> <ics:listget listname="article:headline" fieldname="value" /> </h1> <span class="date"> <ics:getvar name="formattedDate" /> </span> </div> <div class="article post"> <render:getbloburl outstr="imageURL" c="AVIImage" cid='<%=ics.GetVar("imageId") %>' field="largeThumbnail" /> <img class="photo left" src='<ics:getvar name="imageURL" />' /> <render:stream list="bodyList" column="value" /> </div> </cs:ftcs>
Our layout template can then be modified by simply relying on HelloDetail, invoked using the <render:calltemplate>
tag:
<html> <head> <render:calltemplate tname="/Head" args="c,cid" style="element" /> </head> <body class="inner"> <div id="main"> <div id="header"> <render:satellitepage pagename="avisports/navbar" /> </div> <div id="container"> <div class="content"> <render:calltemplate tname="HelloDetail" args="c,cid" /> </div> <div class="side-bar" style="height: 300px"> <!-contains the side nav bar --> </div> </div> <div id="footer"> <render:callelement elementname="avisports/footer" /> </div> </div> </body> </html>
Page templates are Template assets for which the Usage field is set to Element defines a whole HTML page and can be called externally.
A page template has the following characteristics:
In this section we discuss each of these characteristics and then demonstrate a practical application of page templates.
A page template can be invoked from a browser
Like layout templates, a page template can be used to render a web page in a browser by invoking its pagename through the Satellite servlet.
A page template cannot be assigned to an asset
Only layout templates are assignable. Practically speaking, this means that editorial users cannot work in Web Mode of the Contributor interface with a page template, they have to use a layout template.
A page template can be used for previewing
Previewing an asset is different from using Web Mode in the Contributor interface, in the sense that it only allows editorial users to view an asset, there are no editing capabilities involved. When previewing an asset, WebCenter Sites will use, by default, the layout template set in the asset's template field.
When bringing up the Change Preview Template dialog, the template picker shows the following as valid options:
All layout templates applicable to the current asset
All page templates applicable to the current asset
Unlike the Change Layout template picker, selecting a different preview template does not assign this template to the asset's template field. It simply renders the current asset with the selected preview template.
A wrapper is usually not rendering any markup. Instead, a wrapper is usually uncached, and contains business logic meant to be executed before rendering the actual layout template. This is useful when performing such actions as accessing some session data in order to implement security checks, determining which locale should be set, disassembling a friendly URL, etc.
This section presents the following information on wrappers:
A wrapper is a normal SiteEntry asset, for which the Wrapper page flag is set to Yes. This specifies that the asset you are creating is a wrapper page. Selecting the No flag displays the Pagelet only field. See Section 23.6, "Creating SiteEntry Assets" for more information.
Depending on the implementation, it might be necessary to execute a wrapper before rendering an asset with a layout template. When previewing an asset, or when working in Web Mode of the Contributor interface, WebCenter Sites will systematically run a wrapper if there is at least one wrapper enabled on the current site.
If a default preview wrapper has been configured for the current editorial site, WebCenter Sites will use this wrapper. Otherwise, it will use the first wrapper available in the list. If several wrappers are available, a different wrapper can be modified by selecting View and then Preview with Wrapper.
In preview mode, wrappers are especially useful in situations where a layout template requires extra arguments to properly render a web page (for example, a locale argument might be expected) since by default, WebCenter Sites generate a minimal preview URL mainly setting the pagename, with the asset type (c) and asset id (cid) parameters with, respectively, the template pagename, and the type and identifier of the asset to render.
In this case, a preview wrapper can be defined, setting extra arguments as required, and then proceeding by rendering the layout template. Note that the pagename to call is made available in the childpagename
variable.
<cs:ftcs> <% // establish appropriate values for required template arguments %> <ics:setvar name="foo" value="bar" /> <render:satellitepage pagename='<%=ics.GetVar("childpagename")%>' args="c,cid,foo" /> </cs:ftcs> ...