Your Federal Quarterly Tax Payments are due April 15th Get Help Now >>

Xforms Repeat Sample by raja38

VIEWS: 1,372 PAGES: 16

This is the sample document of xforms repeat element it's working status

More Info
									Make the most of XForms repeats

http://www.ibm.com/developerworks/web/library/...

Make the most of XForms repeats
Managing iteration over data sets in your open-standards form Jan J. Kratky, Advisory Software Engineer, IBM  Steve K Speicher (sspeiche@us.ibm.com), Senior Software Engineer, IBM  Summary: XForms provides many powerful mechanisms for working with XML data. One such mechanism is the "repeat" element, which allows you to quickly and easily implement iteration over homogeneous data sets in your XML. In addition, you can format the presentation of such sets as tables, as well as provide dynamic behavior like the insertion and deletion of specific pieces of data within the repeating set. Read on for some tips and tricks on how to make the most of your XForms repeats. Date: 21 Nov 2006 Level: Intermediate Activity: 40 views Comments: 0 (Add comments) Average rating (based on 9 votes) What is an XForms repeat? The repeat element allows you to map your XForms user interface (UI) elements to a homogeneous collection in your XForms document's XML data instance. A "homogenous collection" is taken to be a series of nodes of the same datatype at the same level in the document. For example, in Listing 1, below, the set of bread elements is a homogeneous collection of nodes within the XML instance. Listing 1. A homogeneous collection of XML nodes
<xforms:instance id="in-stock"> <in-stock> <groceries> <perishable> <bread brand="Wonder" quantity="1"/> <bread brand="Merita" quantity="2"/> <bread brand="Arnold" quantity="4"/> </perishable> </groceries> </in-stock> </xforms:instance>

To associate a
1 of 16

repeat

element with the homogeneous set, you simply refer to
Friday 15 May 2009 09:16 AM

Make the most of XForms repeats

http://www.ibm.com/developerworks/web/library/...

it by specifying XPath in the 2, below.

nodeset

attribute of a

repeat

element, as in Listing

Listing 2. Binding a repeat to the homogeneous collection
<xforms:repeat id="bread-repeat" nodeset="instance('in-stock')/perishable/bread"> ...

Notice also in Listing 2 that the repeat was given an refer to it later from other XForms constructs.

id

value, so we can

Now, you can place UI elements within the repeat element, and when you view the form the UI elements will be "unrolled", so that one control will appear for each member in the homogeneous set. Listing 3 shows an XForms input UI element bound to an attribute within the homogeneous set from Listing 1. Notice that the reference into the data instance from the input element is made relative to the nodeset defined for the surrounding repeat. Listing 3. UI elements within a repeat
<xforms:repeat id="bread-repeat" nodeset="instance('in-stock')/groceries/perishable/bread"> <xforms:input ref="@brand"> <xforms:label>Brand of bread: </xforms:label> </xforms:input> </xforms:repeat>

Listing 4 gives an indication of the "unrolled" version that really would be rendered. (You would never see this source when developing the form; it's just here to demonstrate a renderer's interpretation of the repeat construct.) Listing 4. The repeat from Listing 3, unrolled
<xforms:input ref="instance('in-stock')/groceries/perishable/bread[1]/@brand"> <xforms:label>Brand of bread: </xforms:label> </xforms:input> <xforms:input ref="instance('in-stock')/groceries/perishable/bread[2]/@brand"> <xforms:label>Brand of bread: </xforms:label> </xforms:input> <xforms:input ref="instance('in-stock')/groceries/perishable/bread[3]/@brand"> <xforms:label>Brand of bread: </xforms:label> </xforms:input>

2 of 16

Friday 15 May 2009 09:16 AM

Make the most of XForms repeats

http://www.ibm.com/developerworks/web/library/...

Figure 1 shows what this construct looks like when rendered in Mozilla Firefox with the XForms Extension (see Resources for information on how to get the Firefox XForms Extension). Figure 1. The repeat, rendered

Formatting repeats as tables Very often, it makes sense to display data from a homogeneous set in a table format. In the XForms Extension for Firefox, formatting repeats into a display having the appearance of a table requires some work with cascading stylesheets (CSS). First, the source in Listing 5 shows the markup in the body of the document, to which the CSS definitions will apply. Note that the table and column headers are declared with XHTML markup. However, the "body" of the table consists entirely of an XForms repeat. Listing 5. Markup for presenting a repeat as a table
<xhtml:table> <xhtml:tr> <xhtml:thead> <xhtml:th>Brand Name</xhtml:th> <xhtml:th>Quantity</xhtml:th> </xhtml:thead> </xhtml:tr> <xforms:repeat id="bread-repeat" nodeset="instance('in-stock')/groceries/perishable/bread"> <xforms:output ref="@brand"> <xforms:label/> </xforms:output> <xforms:input ref="@quantity">

3 of 16

Friday 15 May 2009 09:16 AM

Make the most of XForms repeats
<xforms:label/> </xforms:input> </xforms:repeat> </xhtml:table>

http://www.ibm.com/developerworks/web/library/...

Listing 6 gives the style definition we'll use for our repeat. The CSS declarations are placed within an XHTML style tag (you can also refer to CSS stored in an external file using the src attribute on the style tag). Listing 6. CSS for styling a repeat as a table
<xhtml:style type="text/css"> @namespace xforms url("http://www.w3.org/2002/xforms"); @namespace xhtml url("http://www.w3.org/1999/xhtml"); xhtml|th { width: 240px; } xforms|repeat .xf-repeat-item { display: table-row; width: 480px; } xforms|repeat xforms|output, xforms|repeat xforms|input { display: table-cell; border: thin; border-style: solid; width: 240px; text-align: center; background-color: lightgray; } </xhtml:style>

Listing 6 approaches the styling by declaring that each item (that is, each row) in the repeat is to be displayed as a row in a table. Then, the next declaration asserts that each XForms output and input control within a repeat will be treated as a table cell, having a solid border and a light gray background. Figure 2 shows the result when rendered in Mozilla Firefox with the XForms Extension. Figure 2. A repeat rendered as a table

4 of 16

Friday 15 May 2009 09:16 AM

Make the most of XForms repeats

http://www.ibm.com/developerworks/web/library/...

There are other stylings that could be used to get a similar effect in Firefox. Furthermore, other XForms renderers might permit different approaches altogether. One example of an alternate approach is the use of some optional attributes defined in the XForms 1.0 specification, particularly repeat-nodeset. These attributes could be placed on a non-XForms element to define a repeating structure that applies to that element's children. Listing 7 shows an example of the usage of repeat-nodeset on the XHTML table element. Listing 7. Using the repeat-nodeset attribute
<xhtml:table> <xhtml:tr> <xhtml:thead> <xhtml:th>Brand Name</xhtml:th> <xhtml:th>Quantity</xhtml:th> </xhtml:thead> </xhtml:tr> </xhtml:table> <xhtml:table xforms:repeat-nodeset="instance('in-stock')/groceries/perishable/bread"> <xhtml:tr> <xhtml:td> <xforms:output ref="@brand"> <xforms:label/> </xforms:output> </xhtml:td> <xhtml:td> <xforms:input ref="@quantity"> <xforms:label/> </xforms:input> </xhtml:td> </xhtml:tr> </xhtml:table>

5 of 16

Friday 15 May 2009 09:16 AM

Make the most of XForms repeats

http://www.ibm.com/developerworks/web/library/...

Using the repeat attributes on non-XForms elements is an elegant approach. It's supported by some XForms implementations, including the XForms Extension for Firefox. Inserting and deleting rows So far, we've looked at presenting repeating structures as they exist in the XML data instance. However, XForms allows users to do much, much more with that data. In particular, it's very common to want to add a new row to a table, or delete an existing row. Listing 8 shows the markup for permitting the user to trigger deletion and insertion of rows in your repeating set. Listing 8. Enabling insert and delete of rows
<xforms:trigger> <xforms:label>Insert Row</xforms:label> <xforms:insert ev:event="DOMActivate" at="index('bread-repeat')" position="after" nodeset="instance('in-stock')/groceries/perishable/bread"/> </xforms:trigger> <xforms:trigger> <xforms:label>Delete Row</xforms:label> <xforms:delete ev:event="DOMActivate" at="index('bread-repeat')" nodeset="instance('in-stock')/groceries/perishable/bread"/> </xforms:trigger>

Listing 8 introduces the concept of a repeat "index". Notice the use of the index() function within the at attribute of the insert and delete actions. The value given in the value of the at attribute represents the 1-based index into the repeat's data set at which the insert or delete will occur. By using the index() function within the value of this attribute, we are specifying that the insert or delete will occur at the currently selected row in the repeat. In the case of the delete action, this means that the currently selected row will be deleted. For the insert action, this means that the new row will be inserted either directly before or after the row at the selected index. Whether the new row is inserted before or after the currently selected row depends on the value given in the insert element's position attribute. When an insert action is triggered, the last row of the repeat is cloned, and it is that clone of the repeat that is inserted. This generally means that the values for the elements and attributes of that row are brought along as well. As this may not be the desired behavior, you may want to follow an insert with a setvalue action to reset the value, as in Listing 9. The index() function is again used to specify the currently-selected row of the repeat as the one on which the setvalue action will occur. This suits the intended purpose -- to target the just-inserted row -- since the insert action resets the repeat's

6 of 16

Friday 15 May 2009 09:16 AM

Make the most of XForms repeats

http://www.ibm.com/developerworks/web/library/...

index to be that of the just-inserted row. Listing 9. Resetting the inserted value
<xforms:trigger> <xforms:label>Insert Row</xforms:label> <xforms:action ev:event="DOMActivate"> <xforms:insert at="index('bread-repeat')" position="after" nodeset="instance('in-stock')/groceries/perishable/bread"/> <xforms:setvalue ref="instance('in-stock')/ groceries/perishable/bread[index('bread-repeat')]/@quantity" value="0"/> </xforms:action> </xforms:trigger>

Implementing triggers for inserting and deleting rows in a repeat is a very common pattern. In fact, automated XForms-generation tools, specifically the IBM® XML Forms Generator (see Resources) will automatically generate triggers for addition and deletion with every repeat. Preventing deletion of the last row In the previous section, we established that an insert action clones the last row in the repeat. This is very bad news when the repeat no longer has any rows, possibly because the user has triggered delete actions on all of them. The net result is that, in the earlier examples, if all rows are deleted, the insert action will no longer do anything. Therefore, you may wish to prevent deletion of the last row. Listing 10 shows one approach, which is to bind the "Delete" trigger to a node in the data model, and then to make that node non-relevant when the count of nodes in the set reaches 1. Listing 10. Preventing deletion of the last row
<xforms:instance id="trigger-controller"> <trigger-sets> <trigger-set> <insert-trigger/> <delete-trigger/> </trigger-set> </trigger-sets> </xforms:instance> <xforms:bind nodeset="instance('trigger-controller')/trigger-set/delete-trigger" relevant="count(instance('in-stock')/groceries/perishable/bread) > 1"/> ...

7 of 16

Friday 15 May 2009 09:16 AM

Make the most of XForms repeats

http://www.ibm.com/developerworks/web/library/...

<xforms:trigger ref="instance('trigger-controller')/trigger-set/insert-trigger"> <xforms:label>Insert Row</xforms:label> <xforms:insert ev:event="DOMActivate" at="index('bread-repeat')" position="after" nodeset="instance('in-stock')/groceries/perishable/bread"/> </xforms:trigger> <xforms:trigger ref="instance('trigger-controller')/trigger-set/delete-trigger"> <xforms:label>Delete Row</xforms:label> <xforms:delete ev:event="DOMActivate" at="index('bread-repeat')" nodeset="instance('in-stock')/groceries/perishable/bread"/> </xforms:trigger>

When the node referenced by the trigger becomes non-relevant, the trigger becomes "unavailable". In Firefox, the default behavior is for the button to disappear from the page, as shown in Figure 3, which shows the form before and after the next-to-last row is deleted. Figure 3. Preventing deletion of the last row

You may wish to experiment with other approaches using the "relevant" property; for example, always making the last row of the repeat non-relevant. That way, the last row can never be selected, and therefore can never be deleted when you are depending on the repeat index to determine the delete location. Listing 11 shows how you might add a "prototype" entry to your data instance, and then add binds to make that last entry always non-relevant. To
8 of 16 Friday 15 May 2009 09:16 AM

Make the most of XForms repeats

http://www.ibm.com/developerworks/web/library/...

ensure that the last row is never displayed, a new CSS entry is made, keying on the ".disabled" CSS cue. The repeat element and its contents require no change at all for this approach. Listing 11. Data with two-deep nesting
<xforms:model> <xforms:instance id="in-stock"> <in-stock> <groceries> <perishable> <bread brand="Wonder" quantity="1" /> <bread brand="Merita" quantity="2" /> <bread brand="Arnold" quantity="4" /> <bread brand="Not sure yet" quantity="0" /> </perishable> </groceries> </in-stock> </xforms:instance> <xforms:bind nodeset="instance('in-stock')/groceries/perishable/bread [count(instance('in-stock')/groceries/perishable/bread)]/ @brand" relevant="false()"/> <xforms:bind nodeset="instance('in-stock')/groceries/perishable/bread [count(instance('in-stock')/groceries/perishable/bread)]/ @quantity" relevant="false()"/> </xforms:model> <xhtml:style type="text/css"> @namespace xforms url("http://www.w3.org/2002/xforms"); xforms|*:disabled { display: none; } </xhtml:style>

For now, using a technique like this is necessary to prevent deletion of your insert prototype. However, there is help on the horizon. The XForms 1.1 specification will address this and other shortcomings with the insert and delete actions, making workarounds like the ones shown here no longer necessary. Nesting repeats The power of XForms really shows itself when you have data that contains homogeneous data sets at different levels, with one nested within the other. For example, Listing 12 shows a data instance in which a top-level homogeneous set of elements consists of the three item elements. Then, each item element contains a set of its own info elements. Listing 12. Data with two-deep nesting

9 of 16

Friday 15 May 2009 09:16 AM

Make the most of XForms repeats

http://www.ibm.com/developerworks/web/library/...

<xforms:instance id="in-stock"> <in-stock> <groceries> <perishable> <item type="bread"> <info brand="Wonder" quantity="1"/> <info brand="Merita" quantity="2"/> <info brand="Arnold" quantity="4"/> </item> <item type="peanut butter""> <info brand="Skippy" quantity="2"/> <info brand="Jif" quantity="1"/> </item> <item type="jelly"> <info brand="Smuckers" quantity="1"/> <info brand="Welch's" quantity="3"/> </item> </perishable> </groceries> </in-stock> </xforms:instance>

XForms makes it easy to iterate over nested sets like this through the nesting of the corresponding repeats. Listing 13 shows how to do it. Listing 13. Defining nested repeats
<xforms:repeat id="bread-repeat" nodeset="instance('in-stock')/groceries/perishable/item"> <xforms:output ref="@type"> <xforms:label>Item type: </xforms:label> </xforms:output> <xforms:repeat id="bread-repeat" nodeset="info"> <xforms:output ref="@brand"> <xforms:label>Brand: </xforms:label> </xforms:output> <xforms:input ref="@quantity"> <xforms:label>Quantity: </xforms:label> </xforms:input> </xforms:repeat> <xhtml:hr/> </xforms:repeat>

Listing 13 defines an output within the outermost repeat, for which each item type is displayed. Then, an inner repeat iterates over the info elements within each item. Notice that the XPath in the inner repat's nodeset attribute is defined relative to the nodeset of its containing repeat. Figure 4 shows how these nested repeats would look in Firefox. Figure 4. The nested repeat, rendered

10 of 16

Friday 15 May 2009 09:16 AM

Make the most of XForms repeats

http://www.ibm.com/developerworks/web/library/...

The power of XForms shows itself once again with the fact that there are no limits to the depth with which you can nest repeats. The only constraints are renderer performance and the desire to maintain a clean, easy-tonavigate interface for the end-user. Managing a repeat's index During our discussion of the insert and delete actions, we touched on the concept of the repeat's index -- that is, the one-based index of the currently selected "row". The user may make the selection, or you can force a selection programmatically in one of two ways. Firstly, you can specify the index of the repeat at the time the form is first rendered by specifying an integer value for the attribute of repeat called startindex. Unlike some of the other XForms facilities for dealing with indices, you cannot specify an XPath expression here; according to the XForms 1.0 specification, only a positive integer value will do. Secondly, you may also set the index of a repeat with the setindex action in response to the user activating a trigger, or perhaps as part of some other action (for example, resetting the index to a desired value after an insert or delete). Listing 14 gives some markup which initially sets the index to 2, and then allows the user to enter a value for the index and set it to that

11 of 16

Friday 15 May 2009 09:16 AM

Make the most of XForms repeats

http://www.ibm.com/developerworks/web/library/...

value by activating the trigger labeled "Select". Listing 14. Using setindex
<xforms:instance id="target-index"> <target-index> <value>1</value> </target-index> </xforms:instance> ... <xhtml:table> <xhtml:tr> <xhtml:thead> <xhtml:th>Brand Name</xhtml:th> <xhtml:th>Quantity</xhtml:th> </xhtml:thead> </xhtml:tr> <xforms:repeat id="bread-repeat" nodeset="instance('in-stock')/groceries/perishable/bread" startindex="2"> <xforms:output ref="@brand"> <xforms:label/> </xforms:output> <xforms:input ref="@quantity"> <xforms:label/> </xforms:input> </xforms:repeat> </xhtml:table> <xforms:input ref="instance('target-index')/value"> <xforms:label>Target Index: </xforms:label> </xforms:input> <xforms:trigger> <xforms:label>Select</xforms:label> <xforms:setindex ev:event="DOMActivate" repeat="bread-repeat" index="instance('target-index')/value"/> </xforms:trigger>

In Listing 14, a data instance has been added to hold the desired value of the repeat index. The input control is bound to this data, so whenever a user enters a new value, that value gets placed in the value element. Finally, the setvalue action tied to the trigger references that same value element in its index attribute, which can take an XPath expression. Figure 5 shows the resulting form in Firefox. Figure 5. Allowing the user to input the repeat index

12 of 16

Friday 15 May 2009 09:16 AM

Make the most of XForms repeats

http://www.ibm.com/developerworks/web/library/...

Figure 5 shows the selected row having a different appearance from the other rows. Without a visual cue like this, it's likely to be unclear to the user which row is currently selected. You can use CSS to provide the user with an indicator of the currently selected row. In Firefox, CSS such as that shown in Listing 15 targets the selected index. Listing 15. Styling for the repeat index
xforms|repeat .xf-repeat-index > xforms|* { color: white; background-color: black; border: none; }

The number attribute The number attribute on the XForms repeat element is a hint to the renderer as to the number of repeat items (or rows) to display at any one time. Support for this attribute is optional for XForms processors, so many renderers do not support it. However, some renderers, such as the FormsPlayer plug-in for Microsoft® Internet Explorer (see Resources), do support the number attribute. Use of the number attribute can permit a cleaner presentation, particularly of repeats over very large sets of data. It may also improve performance, as not every item in the repeat will need to have its associated controls redrawn when the data changes. Let's say that, using the data instance from Listing 1, we want only one row of data to be presented at a time. We would simply add a value of 1 to the repeat element as defined in Listing 2. The result would be as shown in Listing 16.

13 of 16

Friday 15 May 2009 09:16 AM

Make the most of XForms repeats

http://www.ibm.com/developerworks/web/library/...

Listing 16. Applying the number attribute to the repeat
<xforms:repeat id="bread-repeat" nodeset="instance('in-stock')/groceries/perishable/bread" number="1"> ...

Now, it's great that so much space is saved by showing only one repeat row at a time, but a user of this form may want to manipulate the data for a row other than the one initially shown. You can give users the opportunity to access other repeat items by allowing the user to set the current index of the repeat. Listing 17 shows how to enable this by leveraging the setindex action. Listing 17. Allowing navigation of the repeat
<xforms:trigger> <xforms:label>< < Previous</xforms:label> <xforms:setindex ev:event="DOMActivate" repeat="bread-repeat" index="index('bread-repeat') - 1"/> </xforms:trigger> <xforms:trigger> <xforms:label>Next > ></xforms:label> <xforms:setindex ev:event="DOMActivate" repeat="bread-repeat" index="index('bread-repeat') + 1"/> </xforms:trigger>

Listing 17 provides buttons labeled "< < Previous" and "Next > >", which when pressed will decrement and increment, respectively, the index of the repeat. This allows the form's user to scroll back and forth through the data in the repeat. Figure 6 shows what our scrollable repeat would look like in Internet Explorer, using the FormsPlayer plug-in. Figure 6. The scrollable repeat

14 of 16

Friday 15 May 2009 09:16 AM

Make the most of XForms repeats

http://www.ibm.com/developerworks/web/library/...

The power of XForms XForms repeats are one of the more powerful constructs in XForms. If you have not done so already, go ahead and grab a renderer -- such as the free download of the XForms Extension for Mozilla Firefox (see Resources) -- and try these techniques out for yourself.

Resources Learn Dig into XForms at the home page of W3C XForms, which has links to the official XForms specification, as well as to a wide variety of XForms rendering options. Find out more about XHTML, Cascading Style Sheets (CSS), XML, XML Events, XPath, and other related standards at the W3C site. Get products and technologies Mozilla XForms: Render your standards-compliant forms in Mozilla Firefox using this plug-in. Get MozzIE, an open-source control that allows you to render XForms in Internet Explorer. Try FormsPlayer, a plug-in for Internet Explorer that renders XForms. XML Forms Generator: Create functional, standards-compliant forms with a click of the mouse using this Eclipse-based tool from alphaWorks. Visual XForms Designer: Check out the home page, with links to

15 of 16

Friday 15 May 2009 09:16 AM

Make the most of XForms repeats

http://www.ibm.com/developerworks/web/library/...

installation instructions, prerequisites, and the forum. Compound XML Document Toolkit: Explore other open-standard XML markups, including Scalable Vector Graphics (SVG), MathML, VoiceXML, and Synchronized Multimedia Integration Language (SMIL). Discuss Get answers to your questions about the Visual XForms Designer on its discussion forum. About the authors Jan Joseph Kratky is the lead developer for the Compound XML Document Editor and XML Forms Generator. Currently a software engineer with IBM Emerging Software Standards in Research Triangle Park, North Carolina, he holds a B.A. from Cornell University and an M.S. from Rensselaer Polytechnic Institute. A Sun Certified Java Programmer and Sun Certified Web Component Developer, Jan has worked with Java technologies since 1997, and with Eclipse technologies since 2001. Steve Speicher is an IBM Senior Software Engineer working on emerging standards, both infrastructure based and industry verticals (healthcare). He is a member of the W3C Compound Document Formats Working Group, he led the development of the Compound XML Document Toolkit, and he uses Model-Driven Development (MDD) to improve the development of standards. He has previously worked on change and release management tools in the Rational division and in IBM internal tools. Trademarks

16 of 16

Friday 15 May 2009 09:16 AM


								
To top