Skip to main content

Defining Layout Methods

This chapter describes how to create layout methods, which are methods in the template class that describe the layout of your page. This chapter discusses the following topics:

Overview of Layout Methods and Layout Graphs

As noted earlier in this book, a layout method is a method, in a template class, that returns a layout graph. The onGetContent() method of the template class is responsible for invoking the layout methods in the same class. The onGetContent() method can pass two arguments to any layout method:

  • key specifies the key to use when retrieving the layout graph.

  • criteria is any additional criteria to use when retrieving the layout graph.

Formally, a layout graph is a JSON or JavaScript object that meets the following requirements:

  • It must have a children property.

  • The children property must be an array of layout objects.

    Each layout object represents an item within the documentView. The documentView generally displays these items in the same order that they are listed.

  • Each layout object must have a type property, which specifies the overall appearance and behavior of this object

    You can specify additional properties for the object to control the appearance and behavior of the corresponding part of the page. Each object has specific properties. For details, see the plugin reference documentation (see “Plugin Documentation” in the book Using Zen Mojo Plugins).

    Typically you specify properties that determine the value of the layout object, captions or titles to display, and style information.

    Most layout objects support events, if the object has a property named key. You also use this property to refer to that object from within a method (see the chapter “Interacting with Layout Objects”). Conversely, do not specify the key property if it is not needed.

  • The value of any property must be either a valid JavaScript expression, a reference to the current data object, or (in special cases) to variables provided by the layout object.

    Zen Mojo provides special syntax to refer to the current data object or to variables provided by the layout object (see the next section, “Referring to the Current Data Object”).

  • In the layout graph, you can use the Zen macro $$$Text() for localization. The best practice is to use this macro around all user-visible strings within the layout graph.

    Note that the strings are localizable only if the page and template classes both define the DOMAIN parameter. For details on localization, see “Zen Localization” in Developing Zen Applications.

  • The layout graph can have a property named sourceData, which is treated specially. See “Using the sourceData Property in a Layout Graph” later in this chapter.

The following simple example returns a static layout graph (which does not refer to the data object, to any variables, or to the special sourceData object). This example uses layout objects defined in the HTML5 helper plugin (see “Helper Plugin for HTML5” in the book Using Zen Mojo Plugins):

ClientMethod myGetMainViewLayout(key, criteria) [ Language = javascript ]
{
    var myLayoutGraph = {};
    //The standard technique is to have a switch/case construct that creates 
    //branches based on the key argument;
    //In this case only one key value is possible, so there is no need to branch

    myLayoutGraph = {
        children: [
            { type: '$header', $content: $$$Text('Tutorial 1 - Sample Zen Mojo Page')},
            { type: '$p',      $content: $$$Text('This page displays some simple text.')},
            { type: '$p',      $content: $$$Text('Here is another paragraph.') },
        ]
        

    }
    return myLayoutGraph;
}

This method returns an object (called myLayoutGraph within this method), which has a property named children. The children property is an array that contains three objects. The first object is of type $header, and the second and third objects are of type $p. Note the use of the $$$Text() macro.

Referring to the Current Data Object

A layout graph can (and typically does) refer to properties in the data object. To refer to the value of a property (propertyname) of the data object, use '=[propertyname]'

To refer to a property of a property, you can use dot syntax. For example: '=[propertyname.subprop1]'

Similarly, if a property is an array, you can use square brackets and the array item number. For example: '=[arrayprop[3]]' or '=[arrayprop[3].subprop]'

Within a layout graph, when Zen Mojo finds a layout object property with a value of the form '=[propertyname]', it tries to find the given property (propertyname) in the current data object. If it finds the property, Zen Mojo inserts its value into the corresponding part of the layout graph. If it does not find the property, Zen Mojo uses the null value instead. Zen Mojo does not throw an error.

Note:

This syntax applies specifically within a layout graph and is not available elsewhere.

Suppose that the data object for a given documentView has the following properties:

  • name (a string)

  • dob (a string)

  • homeaddress (an object that has the properties street, city, and postalcode)

  • favoritecolors (an array of strings)

The following example layout method displays data for this object. This example also uses layout objects from the HTML5 helper plugin (see “Helper Plugin for HTML5” in the book Using Zen Mojo Plugins).

ClientMethod myGetMainViewLayout(key, criteria) [ Language = javascript ]
{
    var myLayoutGraph = {};
    myLayoutGraph = {
        children: [
            { type: '$header', $content: $$$Text('Data Object Demo Template')},
            { type: '$p', title:'Name', $content:'=[name]' },
            { type: '$p', title:'Birth Date', $content:'=[dob]' },
            { type: '$p', title:'Home City', $content:'=[homeaddress.city]' },
            { type: '$p', title:'First Favorite Color', $content:'=[favoritecolors[1]]' },
            { type: '$p', title:'Number of Favorite Colors', $content:'=[favoritecolors.length]' },
        ]
    }
    return myLayoutGraph;
}
Note:
'=[$variable]' Syntax

A few layout objects support the syntax '=[$variable]', where $variable is a variable provided by the layout object. For example, the $loop layout object defines variable $loopNumber for each item in a loop. See “The $loop Layout Object” in the book Using Zen Mojo Plugins for details and extended examples.

Invoking Template Methods in a Layout Graph

You can invoke a method from within a layout object using the syntax:

myLayoutProperty: '=[$method.methodname]'

where methodname is a string that will be passed to a callback method defined in the template class. When the callback is invoked, it will perform the operation defined for methodname and return an appropriate value.

Use the following general procedure to implement the callback:

  • Specify callback attribute onresolvemethod

    In your page class, add the onresolvemethod attribute to the documentView element of the pageContents XData block. For example:

      onresolvemethod="return zenPage.getTemplate().resolve(context,which);"
    

    where resolve() is the callback method (implemented in the template class) and basePage method getTemplate() returns a reference to the current template. (See “Summary of Callbacks and Event Handlers” for general information on documentView callbacks).

  • Add the callback method to the template class

    The callback method must have a signature of the form methodname(context,which). When invoked, it receives the following arguments:

    • context — is an object that contains properties of the layout object that invoked the callback.

    • which — is string methodname from the '=[$method.methodname]' expression

    The callback method typically implements a switch based on the value of which to determine the appropriate action.

  • Invoke the callback in your layout graph

    The following $p layout object assigns a value to property myValue, and invokes the callback to define property $content:

    { type: '$p', myValue: '345' , $content: '=[$method.readValue]'}
    

    In this example, callback argument which will be string 'readValue', and argument context will hold a variable $instance that resolves to the original layout object (including property myValue).

The following example describes a simple onresolvemethod callback and demonstrates how it is used.

Example: Using the resolve() callback with simple values and loops

This example implements a callback method named resolve(). The onresolvemethod attribute is defined as follows:

  onresolvemethod="return zenPage.getTemplate().resolve(context,which);"

The resolve() method is implemented in the template class:

  ClientMethod resolve(context, which) [ Language = javascript ] {
    switch (which) {
      case 'readValue': return 'myValue = \"' + context.$instance.myValue + '\"';
      case 'readLoop': return 'myLoop('+context.$loopNumber+') = \"' + context.$loopValue + '\"';
    }
  }

The resolve() method deals with two different types of context object:

  • 'readValue' assumes that it will be invoked by a simple layout object, and that context will hold a variable $instance, which resolves to the original layout object.

  • 'readLoop' assumes that the calling object is a $loop. Each time the callback is invoked, it will process the current iteration of the loop using the current values of special loop variables:

    • $loopValue resolves to the data binding of the outer loop and allows direct access to the data for each iteration.

    • $loopNumber is the 1-based iteration count of the loop.

    See “The $loop Layout Object” in the book Using Zen Mojo Plugins for complete details and examples.

The following template method contains a layout graph that uses both callback options. It consists of two main layout objects: $p invokes the callback once (with '=[$method.readValue]'), and $loop invokes it repeatedly (with '=[$method.readLoop]').

  ClientMethod myMainLayout(key, criteria) [ Language = javascript ] {
    var myLayoutGraph = {};
    myLayoutGraph = { children: [
      { type: '$p', myValue: 'a single value' , $content: '=[$method.readValue]'},
      { type: '$loop', value:['nergles','frabsters'], 
        children: [ { type: '$div', $content: '=[$method.readLoop]'} ]
      }
    ]}
    return myLayoutGraph;
  }

The layout objects are rendered as follows:

  • The $p object invokes '=[$method.readValue]', which returns a string that includes the value of layout object property myValue (via context.$instance.myValue).

  • The $loop object defines an array of two values, and invokes '=[$method.readLoop]' once for each of them. Each iteration returns a string value that includes the current loop count (contained in context.$loopNumber), and the current item in the value array (contained in context.$loopValue).

When myLayoutGraph is rendered, the following text is displayed:

    myValue = "a single value"

    myLoop(1) = "nergles"
    myLoop(2) = "frabsters"

Specifying Style Attributes in Layout Graphs

A layout graph has attributes that control its overall style. Within a layout graph, you can specify attributes for layout objects that control their appearance as well.

The following fragment shows an example:

        content = {
            documentStyle:'background:white;min-height:100%;',
            children:[
                {type:'$para',
                    style:'line-height:150%;',
                    blockStyle:'padding-left:20px;padding-bottom:20px;',
                    title:'inbox',
                    titleStyle:'font-size:36px;color:#606060;',
                    text:'Messages and answers you have received',
                },
      ...

Most attributes that control appearance fall into two categories:

  • Some control the style attribute in the corresponding part of the generated HTML. These attributes generally have names like style, blockStyle and so on.

    For these, specify a CSS style instruction.

  • Some control the class attribute in the corresponding part of the generated HTML. These attributes generally have names like paraClass, tableClass and so on.

    For these, specify the name of a CSS class, as given in one of the available CSS style sheets (see the chapter “Including Style Sheets” for details).

Using the sourceData Property in a Layout Graph

Within a layout method, you can bypass the data object, and instead use the special sourceData object.

Specifically, the layout graph can include an object-valued property named sourceData, which is handled specially. In this case, Zen Mojo uses the sourceData object as the current data object, instead of the usual data object.

Important:

If the layout graph includes the sourceData property, Zen Mojo does not invoke the ongetdata callback and does not have access to the data object normally provided by that method.

If the layout graph includes the sourceData property, the syntax '=[propertyname]' refers to properties of the sourceData object.

The following example show an example:

ClientMethod myGetMainViewLayout(key, criteria) [ Language = javascript ]
{

    var myLayoutGraph = {};
    myLayoutGraph = {
        sourceData: {
            name : 'Higgins,Bert',
            dob: '15-July-1973',
            homeaddress: {
                street: '4595 Center Street',
                city: 'Hopkinton',
                postalcode: '89304'
                },
            favoritecolors : ['blue']
            },
        children: [
            { type: '$header', $content: $$$Text('sourceData Demo')},
            { type: '$p', title:'Name', $content:'=[name]' },
            { type: '$p', title:'Birth Date', $content:'=[dob]' },
            { type: '$p', title:'Home City', $content:'=[homeaddress.city]' },
            { type: '$p', title:'First Favorite Color', $content:'=[favoritecolors[1]]' },
            { type: '$p', title:'Number of Favorite Colors', $content:'=[favoritecolors.length]' },
        ]
    }
    return myLayoutGraph;
}

In this example, the sourceData object is defined inline (that is, within the layout graph). You could instead use a reference to an object defined earlier:

        sourceData: myObject

Using Stashed Values within sourceData

The sourceData object provides a convenient way to use values that you have previously stashed on the client, so that you can avoid calling the server unnecessarily. Specifically, you can do the following:

  1. In appropriate places in the client methods, stash values by saving them in properties of the page instance or the template instance. For example:

    zenPage._MyNewValues={name:mainView.getControlValue('enterName'),
                          city:mainView.getControlValue('enterCity')};
    

    For details, see “Stashing Values” in the chapter “Background Information and Tasks.”

  2. When you create a sourceData object, include references to the stashed values.

  3. Within the layout graph, refer to the sourceData object (as previously described in “Using the sourceData Property in a Layout Graph”). That is, use the syntax '=[propertyname]' to refer to properties of the sourceData object.

FeedbackOpens in a new tab