Presenting Complex Data Sets in JSPs

Data binding is the process that ties data to presentation tags in JSPs, thereby creating dynamic web applications that are easy to build and maintain. This topic describes the NetUI Data Binding tags that are used to display large(r) data sets.

NetUI Data Binding tags are complex databinding tags used to render entire data sets to a web page. These tags are stored in the netui-tag-databinding.tld library, which is imported into the JSP by default:

 

<%@ taglib uri="netui-tags-databinding.tld" prefix="netui-data"%>

When you add a NetUI Data Binding component to your JSP, you will notice that the component name is prefixed with "netui-data", for example:

<netui-data:grid dataSource="{pageFlow.allRows}" name="{pageFlow.gridName}">


    ...

</netui-data:grid>

The NetUI Data Binding tags fall into one of the following categories:

The functionality of the various tags are described below. For a detailed description of a tag including its attributes, see JSP Tags Reference, or in Source View, place your cursor inside the tag and press F1.

Note: The netui-data:getData tag, used to bind data to a JSP's page context, is discussed in Using Data Binding in Page Flows. For information on the netui-data:message and netui-data:messageArg tags, see How Do I: Customize Message Formats in Page Flows?

Method Invocation Tags

The method invocation tags netui-data:callControl and netui-data:callPageFlow are used to invoke methods on Controls or PageFlowController instances. The former tag allows access to controls directly from a JSP, while the latter allows controller methods to be called directly from the JSP. While Page Flow actions are not meant to be invoked with the netui-data:callPageFlow tag, calling JPF code from the JSP is useful for localizing code, which is used in many different pages, in a single location.

Repeater Tags

The tags in the repeater tag set are used to render data sets into a JSP page. A reapeater tag is a tag that, given a data set, renders each item or a subset of items in the data set into a page. Let's take a look at an example:

<netui-data:repeater dataSource="{pageFlow.strArr}">
    <netui-data:repeaterHeader>
        <ul>
    </netui-data:repeaterHeader>
    <netui-data:repeaterItem>
        <li>
            <netui:label value="{container.item}" />
        </li>
    </netui-data:repeaterItem>
    <netui-data:repeaterFooter>
        </ul>
    </netui-data:repeaterFooter>
</netui-data:repeater>

The top level tag is netuid-data:repeater, which binds to the complex data set. In the example the complex data set is an array of Strings, which was added to the page flow. The netui-data:repeaterHeader and netui-data:repeaterFooter tags are not repeated but appear only once as the header and the footer. In the example these are used to start and end a bulleted list. The netui-data:repeaterItem contains the code that is repeated. Typically it will contains some html formatting code - in the example <li> and </li> - plus a netui tag that binds to each item in the dataset using the container data binding context. The example will generate a bulleted list with each item in the String array displayed as a separate bullet.

Notice that the repeater tags use tags from the other tag libraries to create formatted data. This is how you ensure that data is displayed in a meaningful way to the user. Another example of netui-data:repeater, which uses a table to format the data, is shown next:

<netui-data:repeater dataSource="{pageContext.vec}">
    <netui-data:repeaterHeader>
        <table border="1">
            <tr>
                <td><b>index</b></td>
                <td><b>name</b></td>
            </tr>
    </netui-data:repeaterHeader>
    <netui-data:repeaterItem>
        <tr>
            <td>
                <netui:label value="{container.index}" />
            </td>
            <td>
                <netui:label value="{container.item}" />
            </td>
        </tr>
    </netui-data:repeaterItem>
    <netui-data:repeaterFooter>
        </table>
    </netui-data:repeaterFooter>
</netui-data:repeater>

The previous two examples showed read-only examples of displaying complex data. However, it is also possible to display complex data in a form and allow the user to change the data. For example, to display a String array and allow the user to change the values, you can use this code:

<netui:form action="submit">
    <netui-data:repeater dataSource="{pageFlow.strArr}">
        <netui-data:repeaterHeader>
            <ul>
        </netui-data:repeaterHeader>
        <netui-data:repeaterItem>
            <li>
                <netui:textBox dataSource="{actionForm.name}" defaultValue="{container.item}" />
            </li>
        </netui-data:repeaterItem>
        <netui-data:repeaterFooter>
            </ul>
        </netui-data:repeaterFooter>
    </netui-data:repeater>
    <netui:button type="submit" value="submit"></netui:button>
</netui:form>

This example will display a bulleted list of strings, with each string in a separate form field. Notice that the netui:textBox receives its default value from the container context and uses the form bean's name property to submit the value. The form bean variable will have to be a String array:

public static class SubmitForm extends FormData
{
    private java.lang.String[] name;
    ...

You can easily create a variable array for a form bean in Action View or Flow View by selecting the array checkbox for a form bean variable in the Edit Form Bean dialog. The necessary getter and setter methods to enable read-write access will then be automatically created for you.

In the action method that is called when submitting the form, you can use standard Java array notation to access the individual elements:

/**
 * @jpf:action
 * @jpf:forward name="success" path="submitPage1.jsp"
*/
protected Forward submit(SubmitForm form)
{
    System.out.println(form.name[1]);
    ...
    return new Forward("success");
}

In the above example, instead of using a form bean to hold the submitted values, we could have used the same String array that we read from to write the values to upon submit. This would require changing the netui:textBox tag in the above JSP code as is shown next:

<netui:form action="submit">
    <netui-data:repeater dataSource="{pageFlow.strArr}">
        ...
        <netui-data:repeaterItem>
            <li>
                <netui:textBox dataSource="{container.item}" />
            </li>
        </netui-data:repeaterItem>
        ...
    </netui-data:repeater>
    <netui:button type="submit" value="submit"></netui:button>
</netui:form>

Notice that the String array is stored in the pageFlow context, so you can access it accordingly in the action method:

  /**
   * @jpf:action
   * @jpf:forward name="success" path="submitPage1.jsp"
   */
  protected Forward submit()
  {
      System.out.println(strArr[1]);
      return new Forward("success");
  }

Nested Repeater Tags and Multi-dimensional Arrays

You can use nested <netui-data:repeater> tags to render a multi-dimensional array.

Suppose you have the following multi-dimensional array.

        String[][] multiDimArr = {  
                                    {"1","2","3","4","5"},
                                    {"a","b","c","d","e"},
                                    {"!","@","#","$","%"},
                                    {"A","B","C","D","E"}
                                 };

You can use one <netui-data:repeater> tag nested inside another to iterate over every element in the multi-dimensional array.

The outer <netui-data:repeater> tag iterates over the outer array.

        <table border="1">
        <netui-data:repeater dataSource="{pageContext.multiDimArr}">
            ...
        </netui-data:repeater>
        </table>

The inner <netui-data:repeater> tag iterates over the elements of the inner arrays.

        <table border="1">
        <netui-data:repeater dataSource="{pageContext.multiDimArr}">
            <tr>
                <netui-data:repeater dataSource="{container.item}">
                    <td><netui:label value="{container.item}" /></td>
                </netui-data:repeater>
            </tr>
        </netui-data:repeater>
        </table>

Notice that the two data binding expressions {container.item} are not synonymous.

The first occurance of {container.item} refers to the elements of the outer array, for example, {"1", "2", "3", "4", "5"}, {"a","b","c","d","e"}, etc. The second occurance of {container.item} refers to the elements of the current inner array, for example, "1", "a", "!", etc. The result is the following HTML table.

    <table border="1">
        <tr>
            <td>1</td>
            <td>2</td>
            <td>3</td>
            <td>4</td>
            <td>5</td>
        </tr>
        <tr>
            <td>a</td>
            <td>b</td>
            <td>c</td>
            <td>d</td>
            <td>e</td>
        </tr>
        <tr>
            <td>!</td>
            <td>@</td>
            <td>#</td>
            <td>$</td>
            <td>%</td>
        </tr>
        <tr>
            <td>A</td>
            <td>B</td>
            <td>C</td>
            <td>D</td>
            <td>E</td>
        </tr>
    </table>

In the browser the table appears as follows.

1 2 3 4 5
a b c d e
! @ # $ %
A B C D E

Additional Repeater Options

The Repeater also provides more advanced features to customize how the items in the data set are displayed, in particular by using padding and choice.

Padding is used in the repeater to create a regular display of an irregular data set. The netui-data:pad tag provides attributes such as maxRepeat, minRepeat, and padText that controls how many container items are displayed, and what to display instead if there are less items than expected. For more information, see the netui:pad reference documentation.

The choice feature is used to create a different display for an item depending on its value. This functionality is implemented using two tags, namely netui-data:choiceMethod and netui-data:choice. The former method is used to indicate the item that is being considered, while the latter method defines a possible value for this item and the display to be rendered when this value is found. Both tags must occur within a netui-data:repeaterItem tag.

Also, the related netui-data:methodParameter tag is embedded within the netui-data:choiceMethod tag, as shown in the following example. You can use the netui-data:methodParameter tag to get the value that will be used by the choice tags.

<netui-data:repeater dataSource="{pageFlow.cart.lineItemList}">
    <netui-data:repeaterHeader>
        ...
    </netui-data:repeaterHeader>
    <netui-data:repeaterItem>
        <netui-data:choiceMethod object="{pageFlow}" method="getShippingState">
            <netui-data:methodParameter value="{container.item.shipState}"/>
        </netui-data:choiceMethod>

        <netui-data:choice value="inTransit">
            ...
            <netui-html:label value="{container.item.name}"/>
            <netui-html:label value="In Transit"/>
            ...
        </netui-data:choice>

        <netui-data:choice value="arrived">
            ...
            <netui-html:label value="{container.item.name}"/>
            <netui-html:label value="Arrived"/>
            ...
        </netui-data:choice>

        <netui-data:choice value="notShipped">
            ...
            <netui-html:label value="{container.item.name}"/>
            <netui-html:label value="Not Yet Shipped"/>
            ...
        </netui-data:choice>

        <netui-data:choice default="true">
            ...
            <netui-html:label value="{container.item.name}"/>
            <netui-html:label value="Error;status unknown./>
            ...
        </netui-data:choice>
    </netui-data:repeaterItem>
    <netui-data:repeaterFooter>
        ...
    </netui-data:repeaterFooter>
</netui-data:repeater>

In the example, the netui-data:choiceMethod tag indicates that the item's shipState must be used to decide which formatting to display. Specifically, its method attribute specifies the method getShippingState, which is a method that is defined in the pageFlow context object, as is indicated in the tag's object attribute. This method getShippingState takes a single argument, the current item's shipState, as is defined in the nested netui-data:methodParameter tag. The various netui-data:choice tags implement what to display given the return value of the getShippingState method for the current item, that is, inTransit, arrived, notShipped, or any other value using the default choice tag. Notice that in the current example some html formatting tags were removed for the sake of clarity. However, you can add html tags to each netui-data:choice tag to render different formatting, for instance to display error values in red, expected values in green, and so forth.

The previous example uses a number of possible static values for the netui-data:choice tag. However, it is also possible to bind its value attribute, as is shown in the following example:

<netui-data:repeater dataSource="{pageFlow.cart.lineItemList}">
    <netui-data:repeaterHeader>
        ...
    </netui-data:repeaterHeader>
    <netui-data:repeaterItem>
        <netui-data:choiceMethod object="{pageFlow}" method="getSpecialItems">
            <netui-data:methodParameter value="{container.item.name}"/>
        </netui-data:choiceMethod>

        <netui-data:choice value="{container.item.name}">
            ...
            <netui-html:label value="{container.item.name}"/>
            <netui-html:label value="Special"/>
            ...
        </netui-data:choice>

        <netui-data:choice default="true">
            ...
            <netui-html:label value="{container.item.name}"/>
            ...
        </netui-data:choice>
    </netui-data:repeaterItem>
    <netui-data:repeaterFooter>
        ...
    </netui-data:repeaterFooter>
</netui-data:repeater>

In the example a new method getSpecialItems, referenced in the netui-data:choiceMethod tag, is used to evaluate each item's name, and it returns the name for special items only (depending on some business logic). The first netui-data:choice tag's value attribute in the example binds to the current item's name, so for special items this value will match the return value of the method, and the formatting defined in this choice tag will be used. All other items will be formatted as defined in the default choice tag.

CellRepeater

The netui-data:cellRepeater is like the netui-data:Repeater tag in that it is used to display each item in a complex data set. The difference is that the netui-data:cellRepeater displays each item in the cell of a table. All the html tags necessary to create the table are automatically created by the cellRepeater tag. For example:

<netui-data:cellRepeater dataSource="{pageFlow.itemArray}" columns="{pageFlow.numColumns}" >
    Item: <netui:label value="{container.item}"/>
</netui-data:cellRepeater>

This example creates a table with a certain number of columns as given in pageFlow.numColumns and as many rows as necessary to display all the items in the data set. Each cell in the table will contain Item: 'the actual item'. The cellRepeater tag has other attributes to determine the formatting of the table and the individual cells. For more information, see the reference documentation for this tag.

Grid Tags

A final repeating databinding tag set is the Grid tag set, which is used to render data from a javax.sql.RowSet object. A RowSet object is used to hold a typically disconnected data set that contains data from a relational database (for more information, see its API reference at http://java.sun.com). The Grid tag set provides the ability to display, page, sort, and filter data. The Grid tag does not display items using standard html formatting tags, and does not use the container data binding context (except for the tag netui-data:expressionColumn). Instead the grid uses specific grid tags to enable table-like formatting and to accomplish data binding, assuming that the same number of columns are rendered for each row in the table.

In WebLogic Workshop you can easily generate a page flow that uses grid tags to display the records in a relational database and contains the action methods to update, insert and delete records. For more information, see How Do I: Create a Database Control Page Flow?

Let's take a look at an example to understand the various grid tags (to see and run the entire example, go to the databasePageFlowController.jpf Sample):

<netui-data:grid dataSource="{pageFlow.allRows}" name="{pageFlow.gridName}">
    <netui-data:gridStyle styleClassPrefix="gridStyle"/>
    <netui-data:pager renderInHeader="true" action="begin" renderInFooter="true"/>
    <netui-data:columns filterable="true" filterAction="begin" sortAction="begin" sortable="true">
        <netui-data:anchorColumn action="getItems" addRowId="true" title="Details"/>
        <netui-data:anchorColumn action="updateItems" addRowId="true" title="Edit"/>
        <netui-data:basicColumn title="Itemnumber" name="itemnumber"/>
        <netui-data:basicColumn title="Itemname" name="itemname"/>
        <netui-data:basicColumn title="Quantityavailable" name="quantityavailable"/>
        <netui-data:basicColumn title="Price" name="price"/>
    </netui-data:columns>
</netui-data:grid>

The following tags are used in the example:

Note: When you filter the data on a column, a new SQL query is generated that is run by the page flow, and the matching records are returned to the RowSet object.

In addition to the tags used in the example, there are several additional tags:

When you select the Grid icon from the Palette window and drag and drop this onto your JSP's Design View or Source View, a dialog will assist you in setting up the grid tag table. You can select the data source, whether to use a Pager (that is, define a netui-data:pager tag), the number of data columns (with netui-data:basicColumn tags), and an anchor column (that is, define a netui-data:anchorColumn tag) that you can make filterable and/or sortable. After clicking OK, go to Source View to associate each column with the corresponding record field in your data source through the column's name attribute.

Related Topics

Using Data Binding in Page Flows

Using Form Beans to Encapsulate Data

Designing User Interfaces in JSPs

How Do I: Customize Message Formats in Page Flows?

How Do I: Create a Database Control Page Flow?

Sample Code

<netui-data:repeater> and related Tags Sample