Displaying data sets with HtmlDataTable

All of the components we've covered so far are relatively simple—they output a string, collect data, allow the user to select an item from a list, or submit a form. If there's one complex requisite standard component for any UI framework, it's a data grid. For desktop applications, you'll find several variations on this theme, regardless of whether you're developing in Swing, .NET, or Delphi. (The same is

1 You may be wondering why the hidden field's value is set in the event handler instead of in the field's declaration. It's set in the event handler so that different HtmlCommandLink components on the same form can have the same parameter but different values.

Table 5.32 HtmlCommandLink example: Using nested UIParameter components

HTML

<a id="myForm:inboxLink" href="#" title="Devora's inbox"

onclick="document.forms['myForm'][ 'myForm:inboxLink'].value= 'myForm:inboxLink'; document.forms[ myForm ][ 1showAllColumns1].value= 1 true 1;

document.forms['myForm'].submit(); return false;" class="button"> <img src=Mimages/inbox.gif"

style="border: 0; padding-right: 5px" alt="" /> Devora's inbox </a>

<input type=Mhidden" name="myForm:inboxLink" /> <input type=Mhidden" name=MshowAllColumns" />

Component Tag

<h:commandLink id=MinboxLinkM action=M#{mailManager.loadInbox}' styleClass=MbuttonM

title="#{user.firstName}'s Inbox"> <h:graphicImage url=Mimages/inbox.gif"

style="border: 0; padding-right: 5px"/> <h:outputText value="#{user.firstName}'s Inbox"/> <f:param name="showAllColumns" value="true"/> </h:commandLink>

Browser Display

Devora's Inbox true for web-based UI frameworks, such as ASPNET WebForms). In JSF, Html-DataTable is the standard data grid.

Technically, HtmlDataTable maps to an HTML <table>, like HtmlPanelGrid. The key difference is that it's designed to work with data sets backed by database results sets, lists, or arrays. As a matter of fact, you can't use it without a dynamic data source. (It is, however, possible to use a list configured via the Managed Bean Creation facility.)

You can use this component simply to display data in a tabular format, or to use input controls to edit the data in your data source. You can also scroll through data sets, displaying a specific number of rows at a time. JSF IDEs provide visual tools for configuring HtmlDataTable components, as shown in figure 5.1.

The component is summarized in table 5.33.

Note that this component has more Java-only properties than most. These properties allow you to better manipulate the component in event listeners (see part 3 for more information).

Figure 5.1 Oracle's JDeveloper [Oracle, JDeveloper] lets you visually manipulate the child components in a table, and also view a table's structure in a separate pane.

Table 5.33 also mentions the fact that columns within an HtmlDataTable are configured using child UlColumn components. Each UlColumn acts as a template for a

Table 5.33 HtmlDataTable summary

Component

HtmlDataTable

Displays an HTML <table>. Columns are specified with child UlColumn components. If the header facet is specified, displays a <thead> element with the contents of the header. If any UlColumn components have a header facet, those will be displayed in

Display

the <thead> element as well. For each row, uses the child UlColumn components as

Behavior

templates for each column. If the first property is specified, starts display with that row. If the row property is specified, displays that many rows total (starting with first). If the footer facet is specified (for this component or child UlColumn components), displays a <tfoot> element with the contents of the footer(s).

Possible IDE Display Names

Data Grid, Data Table

Tag Library

HTML

JSP Tag

<h:dataTable>

Pass-Through Properties

HTML attributes for <table>

Common Properties

id, rendered, styleClass, binding (see table 5.1)

Table 5.33 HtmlDataTable summary (continued)

Property

Type

Default Value

Required?

Description

first

int

0

No

First row number in dataset to display. Change this property to begin displaying a new set of rows.

rows

int

0

No

Number of rows to display at a time. If set to 0 (the default), all rows are displayed.

value

Object

None

The component's current local value. Must be a value-binding expression that references an array, a List, JDBC ResultSet, JSTL ResultSet, or any other type of object. (Other objects are represented as one row).

var

String

None

No

Name of a request-scoped variable under which the current row's object will be stored. Use this value in JSF EL expressions for child components that refer to the current row. (For example, if var is "currentUser", a child component might use the expression "#{currentUser.name}".)

headerClass

String

None

No

Name of CSS style class for the header facet.

footerClass

String

None

No

Name of CSS style class for the footer facet.

rowClasses

String

None

No

Comma-delimited list of CSS style classes for the rows. You can specify multiple styles for a row by separating them with a space. After each style has been applied, they repeat. For example, if there are two style classes (stylel and style2), the first row will be stylel, the second style2, the third stylel, the fourth style2, so on.

column-Classes

String

None

No

Comma-delimited list of CSS style classes for the columns. You can specify multiple styles for a column by separating them with a space. After each style has been applied, they repeat. For example, if there are two style classes (stylel and style2), the first column will be stylel, the second style2, the third stylel, the fourth style2, so on.

Table 5.33 HtmlDataTable summary (continued)

Java-Only Property

rowCount

int

None

No

Returns the total number of available rows (read-only); returns -1 if the total number is not known.

rowIndex

int

None

No

Returns the index of the currently selected row (-1 if there is no selected row).

rowData

Object

None

No

Returns the currently selected row, if available (read-only).

row-Available

boolean

None

No

Returns true if rowData is available at the current rowIndex (read-only).

Facet

Description

header

Child components displayed as the table's header.

footer

Child components displayed as the table's footer.

specific column; its contents are repeated for each row that is displayed. This component also has header and footer facets, and it's summarized in table 5.34.

Table 5.34 UIColumn summary

Component

UIColumn

Family

javax.faces.Column

Display Behavior

None (used to define a column In HtmlDataTable)

Possible IDE Display Names

N/A

Tag Library

HTML

JSP Tag

<h:column>

Pass-Through Properties

None

Common Properties

id, rendered, binding (see table 5.1)

Table 5.34 UIColumn summary (continued)

Facet

Description

header

Child components displayed as the table's header.

footer

Child components displayed as the table's footer.

UlColumn only has three properties, and although it can be used in third-party components, the only standard component that utilizes it is HtmlDataTable.

HtmlDataTable is the most powerful standard component, so it's no surprise that there are a lot of ways you can use it. Let's start with the simple example shown in table 5.35.

Table 5.35 HtmlDataTable example: Creating a simple read-only table

<table border="1" cellspacing="2">

<thead>

<tr>

<th scope="col">First Name</th>

<th scope="col">Last Name</th>

<th scope="col">Balance</th>

</tr>

</thead>

<tbody>

<tr>

<td>Devora</td>

< td>Shapiro</td>

<td>$32,495.00</td>

</tr>

<tr>

HTML

< td>John</td>

< td>Mann</td>

<td>$1,200.00</td>

</tr>

<tr>

<td>Joe</td>

<td>Broke</td>

<td>$0.00</td>

</tr>

<tr>

<td>MW</td>

< td>Mann</td>

<td>$5,050.00</td>

</tr>

</tbody>

</table>

continued on next page

Table 5.35 HtmlDataTable example: Creating a simple read-only table (continued)

Component Tag

<h:dataTable value="#(userList}" var="user" border="1" cellspacing="2">

<f:facet name="header">

<h:outputText value="First Name"/> </f:facet>

<h:outputText value="#{user.firstName}"/> </h:column> <h:column>

<f:facet name="header">

<h:outputText value="Last Name"/> </f:facet>

<h:outputText value="#{user.lastName}"/> </h:column> <h:column>

<f:facet name="header">

<h:outputText value="Balance"/> </f:facet>

<h:outputText value="#{user.balance}">

<f:convertNumber type="currency"/> </h:outputText> </h:column> </h:dataTable>

Browser Display

Here, we have a simple HTML table with First Name, Last Name, and Balance columns. The data comes from a list that currently has four User objects. In the HtmlDataTable declaration, child UIColumn components are used to define templates for each column in the output. So, the header facet of each UIColumn is displayed within the table's header, and the contents of each UIColumn are repeated for every row in the list.

HtmlDataTable and its child UIColumn components output the structure of the table, iterating through the rows in the list. The cellpadding and border properties of the HtmlDataTable are passed through. However, the var property is used as the name of a request-scoped variable that can be used by child components— HtmlOutputText components in this case. This is why the child components can reference a bean called user—the HtmlDataTable is making the current row available under that name. Also, note that we used a converter for the last HtmlOutputText component; this allows us to format the user.balance property as a currency (see chapter 6 for more on converters).

HtmlDataTable is useful for displaying data sets in a tabular format, but its real power is the ability to edit those data sets. All you need to do is place input and Command controls inside the table, and associate the Command controls with backing bean methods, as shown in table 5.36.

This example does a lot, so let's start by comparing it to the previous one. There are a few major changes:

  • The HtmlDataTable component has several style-related properties for the header and footer facets, and the even and odd rows. These CSS styles are defined in a separate stylesheet included on the page, and spruce up the overall appearance.
  • The HtmlDataTable component's binding property references userEdit-Form.userDataTable. This allows userEditForm to access the component on the server.
  • We've added a header and footer facet for the HtmlDataTable. The header facet has a single HtmlOutputText component. The footer facet has two HtmlCommandButton components—one simply submits the data (and doesn't call any action listeners), and the other resets the form data.
  • We replaced the HtmlOutputText components for the columns in the previous example with HtmlinputText columns so that the user can edit bean properties.
  • We added a third Registered column that simply displays the value of the user.registered property.
  • We added a fourth column with an HtmlCommandLink component that allows the user to delete the current row by calling the action listener method userEditForm.deleteUser. Internally, this method accesses the list through the HtmlDataTable component (which it can access because of the component's binding property).

The result is that you can edit the first name, last name, or balance of any of the listed users and JSF will update the underlying rows when you click the Submit button automatically. If you click the Reset button, the browser will reset the input fields to their original values (because the last update)—no server roundtrip will be made. Clicking the Delete button deletes the associated row from the data set and updates any other rows that may have been edited; the actual work of removing the item is performed by the editUserForm.deleteUser method, and everything

Table 5.36 HtmlDataTable example: Using nested Input and Command components to edit a data set

HTML

<table class = "table-background" cellpadding="5" cellspacing="5"> <thead> <tr>

<th class="headers" colspan="5" scope="colgroup"> <span class="table-header">Edit user information </span>

<th class="headers" scope="col">First Name</th> <th class="headers" scope="col">Last Name</th> <th class="headers" scope="col">Balance</th> <th class="headers" scope="col">Registered?</th> <th class="headers" scope="col"></th> </tr> </thead> <tfoot> <tr>

<td class="table-footer" colspan="5">

<input type="submit" name="_id1:_id20:_id37"

value="Submit" /> <input type="reset" name="_id1:_id20:_id38" value="Reset" />

</td> </tr> </tfoot> <tbody>

<tr class="table-odd-row"> < td>

<input id="_id1:_id2 0:0:inputName" type="text"

name="_id1:_id2 0:0:inputName" value="Devora" />

<input type="text" name= value="Shapiro" /

<input type="text" name= value="$32i495.00"

onclick="document.forms value document-forms id1:_id20:0:_id26"

return false;">Delete

<tr class="table-even-row"> < td>

<input id="_id1:_id2 0:3:inputName" type="text" name="_id1:_id2 0:3:inputName" value="MW"

<input type="text" name="_id1:_id2 0:3:_id2 6" value="Mann" />

<input type="text" name="_id1:_id2 0:3:_id2 9" value="$5,050.00" />

onclick="document.forms value document-forms id1'][v_id1:_id20:3:_id34'] id1:_id20:3:_id34'; id1'].submit();

return false;">Delete

</a> </td> </tr> </tbody> /table>

Table 5.36 HtmlDataTable example: Using nested Input and Command components to edit a data set (continued)

Component Tag

<h:dataTable value="#{userList}M var="user" styleClass=Mtable-background"

headerClass="headers" footerClass="table-footer" rowClasses="table-odd-row# table-even-row" cellspacing="5" cellpadding="5" binding="#{userEditForm.userEditTable}"> <f:facet name="header">

<h:outputText value="Edit user information" styleClass="table-header"/>

<f:facet name="header">

<h:outputText value="First Name"/> </f:facet>

<h:inputText id="inputName" value="#{user.firstName}"/> </h:column> <h:column>

<f:facet name="header">

<h:outputText value="Last Name"/> </f:facet>

<h:inputText value="#{user.lastName}"/> </h:column> <h:column>

<f:facet name="header">

<h:outputText value="Balance"/> </f:facet>

<h:inputText value="#{user.balance}">

<f:convertNumber type="currency"/> </h:inputText> </h:column> <h:column>

<f:facet name="header">

<h:outputText value="Registered?"/> </f:facet>

<h:outputText value="#{user.registered}"/> </h:column> <h:column>

<h:commandLink actionListener="#{userEditForm.deleteUser}

<h:outputText value="Delete"/> </h:commandLink> </h:column>

<f:facet name="footer"> <h:panelGroup>

<h:commandButton value="Submit"/> <h:commandButton value="Reset" type="reset"/> </h:panelGroup> </f:facet> </h:dataTable>

Browser Display

Edit user information

First Name Last Name

Balance

¡Devora

| Shapiro

$32,495.00

1 John

J |Mann

j$t .200.00

Joe

Broke

moi

MW

:Mann

false false

Delete Delete false Delete false Delete

[ Submit ]| Reset else is handled by JSF. Because the Command components don't have the action property set, no navigation takes place—the view is always redisplayed.

We are leaving out a piece of the puzzle—the Java code for editUserForm. deleteUser. For more information on writing Java code that interacts with HtmlDataTable, see chapter 13. Even though some Java code is required, HtmlDataTable does a lot of work on its own—using the proper child components, you can display and edit data without code. It can even scroll through a data set, displaying parts of it at a time; see chapter 10 for a real-world example.

0 0

Post a comment

  • Receive news updates via email from this site