Getting started with the Cell Templates

by Lucio Bordonaro
10,223 views Published on Oct 24, 2011
Applies to: 7.2 or higher
Table of contents

Introduction

A Cell is the Grid container of View Components, sub-Pages and sub-Grids. A Cell Template is typically used to create a unique template for several elements, for instance two different View Components, and treat them in the same template, resulting like a single View Component.

Cell Layout Template

Basic Example

Before starting developing a Cell template you need to consider the layout XML structure since you will use it to retrieve items you want to show.

The Layout XML of a Cell is composed of the Layout XML of all the elements in it. In a Cell template, using a Groovy scriptlet, it is possible to access to the structure of every element and treat it as a single element in the template.

Consider this example; we will use a Cell Template to print in a single table the first two attributes of both the Details Components we have inside a Cell.

This is the related Grid Layout structure, respectively of the page and the cell:

And here's a Layout XML of the cell containing two data units:

<layout:Cell xmlns:layout="http://www.webratio.com/2006/WebML/Layout" _sel="t">
    <layout:Unit unitId="dau1" _sel="t" layout:expanded="true" xmlns:gr="http://www.webratio.com/2006/WebML/Graph" gr:x="0" gr:y="125" id="dau1" name="User Info" entity="User" displayAttributes="att9 userName att33 email att30 att32 att31 userOID password att34" unitTagName="DataUnit">
        <layout:Attribute attribute="att9" _sel="t" id="att9" name="full name" type="string" derivationQuery="calculated::Self.att30 || ' ' || Self.att31" xmlns:db="http://www.webratio.com/2006/WebML/Database" db:table="USER_FULL_NAME_VIEW" storageType="file" db:column="DER_ATTR">
            <db:JoinColumn attribute="userOID" name="OID"/>
        </layout:Attribute>
        <layout:Attribute attribute="userName" _sel="t" name="username" id="userName" type="string" xmlns:db="http://www.webratio.com/2006/WebML/Database" db:column="USERNAME"/>
        <layout:Attribute attribute="att33" _sel="t" id="att33" name="birth date" type="date" xmlns:db="http://www.webratio.com/2006/WebML/Database" db:column="BIRTH_DATE"/>
        <layout:Attribute attribute="email" _sel="t" name="email" id="email" type="string" xmlns:db="http://www.webratio.com/2006/WebML/Database" db:column="EMAIL"/>
        <layout:Attribute attribute="att30" _sel="t" id="att30" name="first name" type="string" xmlns:db="http://www.webratio.com/2006/WebML/Database" db:column="FIRST_NAME"/>
        <layout:Attribute attribute="att32" _sel="t" id="att32" name="gender" type="string" xmlns:db="http://www.webratio.com/2006/WebML/Database" db:column="GENDER"/>
        <layout:Attribute attribute="att31" _sel="t" id="att31" name="last name" type="string" xmlns:db="http://www.webratio.com/2006/WebML/Database" db:column="LAST_NAME"/>
        <layout:Attribute attribute="userOID" _sel="t" name="oid" id="userOID" type="integer" key="true" xmlns:db="http://www.webratio.com/2006/WebML/Database" db:column="OID"/>
        <layout:Attribute attribute="password" _sel="t" name="password" id="password" type="password" xmlns:db="http://www.webratio.com/2006/WebML/Database" db:column="PASSWORD"/>
        <layout:Attribute attribute="att34" _sel="t" id="att34" name="shipping address" type="string" xmlns:db="http://www.webratio.com/2006/WebML/Database" db:column="SHIPPING_ADDRESS"/>
        <Selector id="su4" defaultPolicy="fill" booleanOperator="and" _sel="t">
            <KeyCondition id="kcond3" name="User" predicate="in" implied="false" _sel="t"/>
        </Selector>
    </layout:Unit>
    <layout:Unit unitId="dau2" _sel="t" layout:expanded="true" xmlns:gr="http://www.webratio.com/2006/WebML/Graph" gr:x="100" gr:y="125" id="dau2" name="Group Info" entity="Group" displayAttributes="groupName groupOID" unitTagName="DataUnit">
        <layout:Attribute attribute="groupName" _sel="t" name="group name" id="groupName" type="string" xmlns:db="http://www.webratio.com/2006/WebML/Database" db:column="GROUP_NAME"/>
        <layout:Attribute attribute="groupOID" _sel="t" name="oid" id="groupOID" type="integer" key="true" xmlns:db="http://www.webratio.com/2006/WebML/Database" db:column="OID"/>
        <Selector id="su6" defaultPolicy="fill" booleanOperator="and" _sel="t">
            <RelationshipRoleCondition id="rcond1" predicate="in" implied="false" name="User" role="User2DefaultGroup" _sel="t"/>
        </Selector>
    </layout:Unit>
</layout:Cell>

Now the idea is parsing the XML structure using groovy’s selectSingleNode and selectNodes  methods to retrieve the information regarding each View Component contained in the cell.
Different criteria like by position, by type, by name can be used to retrieve different objects.
All this criteria are expressed using the XPath language.

#?delimiters [%, %], [%=, %]
[%       setHTMLOutput()

//select the first unit in the cell
def firstUnit = cell.selectSingleNode("layout:Unit[1]")

//select the first attribute of the first unit in the cell
def firstUnitFirstAttribute = firstUnit.selectSingleNode("layout:Attribute[1]")

//select the second attribute of the first unit in the cell                                                
def firstUnitSecondAttribute = firstUnit.selectSingleNode("layout:Attribute[2]")

//select the second unit in the cell                                                                                
def secondUnit = cell.selectSingleNode("layout:Unit[2]")

//select the first attribute of the second unit in the cell
def secondUnitFirstAttribute = secondUnit.selectSingleNode("layout:Attribute[1]")

//select the second attribute of the second unit in the cell                                                
def secondUnitSecondAttribute = secondUnit.selectSingleNode("layout:Attribute[2]")     %]

<wr:Frame>
    <table>
        <tr>
            <th>
                <wr:Label context="firstUnitFirstAttribute"/>
            </th>
            <td>
                <wr:Value context="firstUnitFirstAttribute"/>
            </td>
        </tr>
        <tr>
            <th>
                <wr:Label context="firstUnitSecondAttribute"/>
            </th>
            <td>
                <wr:Value context="firstUnitSecondAttribute"/>
            </td>
        </tr>
        <tr>
            <th>
                <wr:Label context="secondUnitFirstAttribute"/>
            </th>
            <td>
                <wr:Value context="secondUnitFirstAttribute"/>
            </td>
        </tr>
        <tr>
            <th>
                <wr:Label context="secondUnitSecondAttribute"/>
            </th>
            <td>
                <wr:Value context="secondUnitSecondAttribute"/>
            </td>
        </tr>
        <tr>
            <wr:Iterate var="l" context="firstUnit" select="layout:Link">
                <td><wr:Link/></td>
            </wr:Iterate>
        </tr>
        <tr>
            <wr:Iterate var="l" context="secondUnit" select="layout:Link">
                <td><wr:Link/></td>
            </wr:Iterate>
        </tr>
    </table>
</wr:Frame>

Note the use of the context attribute in wr:Label and wr:Value tags, using the variables previously defined in a Groovy scriplet and the use of the wr:Iterate tags with the two variables "firstUnit" and "secondUnit", printing all the links defined in the units. Moreover, it's important to specify that normally Cell templates are not intended for general use, but are developed basing on a specified and particular need (in this case, this cell template works only with two data units with at least two attributes each).

Advanced Example

Now it's possible to see a more complex example: suppose that you want to make a tab based index, where the products list is shown at the top of the cell like tabs and then the list of related combination is shown in each tab content. To accomplish this, you need a complex structure composed of two Simple List View Component, the first showing all the products, the second showing the related combinations, filtered using a relationship role condition. A flow between the two components passes the product's key from the source to the target.

By placing the two components in a single cell, it is possible to write a Cell Template to create the "tab-style" index. Here is the Page and Cell layout structure:

This is the Layout XML of the cell containing the two Simple Lists.

<layout:Cell xmlns:layout="http://www.webratio.com/2006/WebML/Layout" _sel="t">
    <layout:Unit unitId="inu1" _sel="t" layout:expanded="true" xmlns:gr="http://www.webratio.com/2006/WebML/Graph" gr:x="0" gr:y="10" id="inu1" name="Products" entity="ent8" displayAttributes="att41" linkOrder="ln6" unitTagName="IndexUnit">
        <layout:Attribute attribute="att41" _sel="t" name="name" id="att41" type="string" xmlns:db="http://www.webratio.com/2006/WebML/Database" db:column="NAME"/>
        <layout:Link link="ln6" _sel="t" id="ln6" name="Choose" to="inu2" automaticCoupling="false" type="normal" validate="true">
            <LinkParameter id="ln6_par1" source="data[].att38" target="rcond4.att38" _sel="t"/>
            <LinkParameter id="ln6_att38" source="data[].att38" target="inu1.current.att38" _sel="t"/>
        </layout:Link>
        <SortAttribute attribute="att41" order="ascending" _sel="t"/>
        <Link id="ln6" name="Choose" to="inu2" automaticCoupling="false" type="normal" validate="true" _sel="t">
            <LinkParameter id="ln6_par1" source="data[].att38" target="rcond4.att38" _sel="t"/>
            <LinkParameter id="ln6_att38" source="data[].att38" target="inu1.current.att38" _sel="t"/>
        </Link>
    </layout:Unit>
    <layout:Unit unitId="inu2" _sel="t" layout:expanded="true" xmlns:gr="http://www.webratio.com/2006/WebML/Graph" gr:x="145" gr:y="0" id="inu2" name="Combinations" entity="ent4" displayAttributes="att3 att5 att6 att21" unitTagName="IndexUnit">
        <layout:Attribute attribute="att3" _sel="t" name="code" id="att3" type="integer" xmlns:db="http://www.webratio.com/2006/WebML/Database" db:column="CODE"/>
        <layout:Attribute attribute="att5" _sel="t" name="name" id="att5" type="string" xmlns:db="http://www.webratio.com/2006/WebML/Database" db:column="NAME"/>
        <layout:Attribute attribute="att6" _sel="t" name="price" id="att6" type="float" subType="sbt1" xmlns:db="http://www.webratio.com/2006/WebML/Database" db:column="PRICE"/>
        <layout:Attribute attribute="att21" _sel="t" name="end date" id="att21" type="date" xmlns:db="http://www.webratio.com/2006/WebML/Database" db:column="END_DATE"/>
        <Selector id="su7" defaultPolicy="fill" booleanOperator="and" _sel="t">
            <RelationshipRoleCondition id="rcond4" name="Product" role="rel1" predicate="in" implied="false" _sel="t"/>
        </Selector>
        <SortAttribute attribute="att21" order="descending" _sel="t"/>
    </layout:Unit>
</layout:Cell>

This is the code of the Cell Layout template.
Pay attention to the position of the attributes for the two Simple Lists.

#?delimiters [%, %], [%=, %]
[%     setHTMLOutput()
//the first Index Unit (showing the products)
def products = cell.selectSingleNode("layout:Unit[1]")

//the first attribute of the products index (product name)
def productsName = products.selectSingleNode("layout:Attribute[1]")

//the second Index Unit (showing the combinations)
def combinations = cell.selectSingleNode("layout:Unit[2]")

//the first attribute of the combination index (combination name)
def combinationsName = combinations.selectSingleNode("layout:Attribute[1]") 

//the first (and unique) link of the products index
def selectionFlow = products.selectSingleNode("layout:Link") %]

<wr:Frame>
    <table>
        <!-- the first row contains all the products names -->
        <tr>               
            <c:forEach var="current" varStatus="status" items="${[%=products['id']%].data}">
                <c:set var="index" value="${status.index}"/>
                <td class="link" style="background: #eaeaea; border: 2px solid white;">  
                <!-- creates an anchor using the search link and showing the products name -->
                    <a href="<wr:URL context="selectionFlow"/>" class="link">
                        <!-- the product name is rendered as a link, by clicking on it, the search link is followed -->
                        <wr:Value context="productsName"/>
                    </a>
                </td>
            </c:forEach>              
        </tr>
        <!-- in the second row there's the list of related combinations -->
        <tr>
            <!-- the index variable (defined in the forEach tag) is used to set the colspan -->
            <td colspan="${index +1}">
                <ul style="margin-top: 20px;">
                    <c:forEach var="current" varStatus="status" items="${[%=combinations['id']%].data}">
                        <c:set var="index" value="${status.index}"/>
                        <!-- clicking follows the search link and computes the second index unit, showing all the related combinations name -->
                            <li><wr:Value context="combinationsName"/></li>
                    </c:forEach>
                </ul>
            </td>
        </tr>
    </table>
</wr:Frame>

This is the result in the web page.

 

 
 

Attachments

template 4 KB
template 4 KB