programming wdk datagrid

21
Programming WDK datagrid February 2009, article by Mirza Fazlic, [email protected] This article will introduce the reader to the WDK datagrid control and cover some of the common development tasks encountered when working with databound controls. You should be familiar with the basic WDK concepts such are actions, component behavior classes, controls etc. PROGRAMMING WDK DATAGRID .................................................................................................... 1 Introduction.............................................................................................................................................................................................. 1 Databinding Overview............................................................................................................................................................................. 2 Core datagrid Controls............................................................................................................................................................................ 2 Supporting datagrid controls .................................................................................................................................................................. 7 Table headers and footers...................................................................................................................................................................... 7 Column Sorting ..................................................................................................................................................................................... 7 Data Paging ........................................................................................................................................................................................... 7 Row Filtering ........................................................................................................................................................................................ 8 Output Formatting ................................................................................................................................................................................. 8 Developing a custom value formatter..................................................................................................................................................... 9 Developing custom databound controls ............................................................................................................................................... 12 Row selection processing ....................................................................................................................................................................... 15 ActionMultiSelect ............................................................................................................................................................................... 16 Manually getting selected rows in a component class......................................................................................................................... 16 Datagirdrowevent ................................................................................................................................................................................ 19 Conclusion .............................................................................................................................................................................................. 21 References ............................................................................................................................................................................................... 21 Introduction Almost every web application has to deal with data, whether stored in a database, repository, an XML file or something else. Fetching this data is only part of the game — a sophisticated and modern application framework needs to provide developers an easy to use, flexible and attractive way to manage displaying this data. Applications developed using the WDK framework are no different. The retrieved data is typically a list of objects or documents stored in the repository. Using WDK datagrid control, these objects can easily be rendered and presented in a tabular form by your custom component, including interspersed hyperlinks to provide interactive functionalities such as sorting, paging and row selection processing. Datagrid and its associated controls use a process known as databinding to accomplish this.

Upload: spamreader

Post on 22-Oct-2015

241 views

Category:

Documents


13 download

TRANSCRIPT

Page 1: Programming WDK Datagrid

Programming WDK datagrid February 2009, article by Mirza Fazlic, [email protected] This article will introduce the reader to the WDK datagrid control and cover some of the common development tasks encountered when working with databound controls. You should be familiar with the basic WDK concepts such are actions, component behavior classes, controls etc.

PROGRAMMING WDK DATAGRID ....................................................................................................1

Introduction..............................................................................................................................................................................................1

Databinding Overview.............................................................................................................................................................................2

Core datagrid Controls............................................................................................................................................................................2

Supporting datagrid controls..................................................................................................................................................................7 Table headers and footers......................................................................................................................................................................7 Column Sorting .....................................................................................................................................................................................7 Data Paging ...........................................................................................................................................................................................7 Row Filtering ........................................................................................................................................................................................8 Output Formatting.................................................................................................................................................................................8

Developing a custom value formatter.....................................................................................................................................................9

Developing custom databound controls ...............................................................................................................................................12

Row selection processing .......................................................................................................................................................................15 ActionMultiSelect ...............................................................................................................................................................................16 Manually getting selected rows in a component class.........................................................................................................................16 Datagirdrowevent................................................................................................................................................................................19

Conclusion ..............................................................................................................................................................................................21

References...............................................................................................................................................................................................21

Introduction Almost every web application has to deal with data, whether stored in a database, repository, an XML file or something else. Fetching this data is only part of the game — a sophisticated and modern application framework needs to provide developers an easy to use, flexible and attractive way to manage displaying this data. Applications developed using the WDK framework are no different. The retrieved data is typically a list of objects or documents stored in the repository. Using WDK datagrid control, these objects can easily be rendered and presented in a tabular form by your custom component, including interspersed hyperlinks to provide interactive functionalities such as sorting, paging and row selection processing. Datagrid and its associated controls use a process known as databinding to accomplish this.

Page 2: Programming WDK Datagrid

NOTE: While this article was written for WDK 6.5, most of the concepts apply to all WDK versions. We will discuss important and relevant attributes of databound controls. It is beyond the scope of this document to cover ALL available control attributes; such information is available to the user in the WDK Reference Guide.

Databinding Overview Databinding is a feature that allows us to “bind” or associate retrieved data to one or more web controls and have the control automatically display that data. This prevents us from having to write time-consuming logic to loop over multiple rows and manipulate individual fields to produce the visual output. Instead, a data provider is used to feed the data to the controls, while controls themselves are responsible for generating the appropriate HTML. The databinding can be single or bi-directional. Unfortunately, WDK supports only one-way binding. The UI elements are rendered based on the underlying bound data; however, user interaction with UI controls is NOT automatically propagated all the way back to the data provider. This is one of the big disadvantages of WDK framework, as developers typically have to write large amounts of manual code to process these changes. Databound controls are typically placed inside a databound container, such is a datagrid. The container control is responsible for iterating over the rows of the data provider, while the contained databound controls extract the individual columns (we will demonstrate later how to access the data provider from within your custom control). A databound control typically has the following syntax:

All standard WDK controls, such are Labels, Textboxes, Checkboxes etc. support databinding and bind to data provider via datafield attribute.

Core datagrid Controls In its simplest form, the datagrid displays a bare-bones HTML table, but it can be enhanced to output a much richer UI, with hyperlinks for column-based sorting, row filtering, paging navigation etc. Let’s examine the minimum datagrid configuration required. We will later expand on this example and demonstrate the use of numerous supporting datagrid controls. At the very minimum, a datagrid requires the following three controls:

• Datagrid – top level container controlling the entire table. • Datagridrow – row level container controlling the individual table rows.

<datacontainer_control> <databound_control datafield=”field_name” /> <datacontainer_control>

Page 3: Programming WDK Datagrid

• Datagridrowtd – controls the individual table cells. The following JSP page shows a datagrid that uses a simple query to list all objects of type “article_document”. Note that the DQL query is specified directly as an attribute of the datagrid control:

Every databound control and its data provider must be provided a valid repository session; therefore, in your component behavior class, you need to call the setDfSession method on the provider. For example, in the onInit method:

The example above used a very simple DQL query. This is often not the case in real life, where we have to programmatically manipulate and build up the query. Setting database queries directly in the UI layer is a questionable approach itself, and it is something that should be used only during development. Instead, we can set the query in the component behavior class. In the following example, we build up the query to return only the documents of the currently logged in user:

public void onInit(com.documentum.web.common.ArgumentList args) { super.onInit(args); Datagrid dg = (Datagrid)getControl("dgCustomList",Datagrid.class); dg.getDataProvider().setDfSession(getDfSession()); };

<dmf:datagrid name="dgCustomList" width="100%" query="SELECT r_object_id, object_name, length_size, width_size FROM article_document"> <dmf:datagridRow> <dmf:datagridRowTd> <dmf:label datafield="r_object_id" /> </dmf:datagridRowTd> <dmf:datagridRowTd> <dmf:label datafield="object_name" /> </dmf:datagridRowTd> <dmf:datagridRowTd> <dmf:label datafield="length_size" /> </dmf:datagridRowTd> <dmf:datagridRowTd> <dmf:label datafield="width_size" /> </dmf:datagridRowTd> </dmf:datagridRow> </dmf:datagrid>

Page 4: Programming WDK Datagrid

Method to construct the query is simplified for the purposes of the example as follows: Another typical scenario is when the query itself is not sufficient for our purposes and we need to additionally pre-process or manipulate the data before we display it (or perhaps, as in the example below, we need to add additional column that is not actually represented in the object model). In this case, instead of a query, we can also bind the datagrid directly to an instance of a ScrollableResultSet. Please note that unless absolutely necessary, this is often not the most efficient solution, especially for large sets of data. The processing will happen for every record, regardless of how many are actually being rendered; instead, as we will show later, it is better to write a custom databound control. In the JSP page, we add additional column and bind it to the field area:

public void onInit(ArgumentList args) { super.onInit(args); String ownerName = null; try { ownerName = getDfSession().getLoginUserName();

String fullQuery = getQueryForUsersDocuments(ownerName); Datagrid dg = (Datagrid)getControl("dgCustomList",Datagrid.class); dg.getDataProvider().setDfSession(getDfSession()); dg.getDataProvider().setQuery(fullQuery); } catch (DfException dfe) { throw new WrapperRuntimeException("Error getting user", dfe); }

protected String getQueryForUsersDocuments(String ownerName) { //dummy code here to build up a query based on user name return "SELECT r_object_id, object_name, length_size, width_size " + "FROM article_document " + "WHERE owner_name = '" + ownerName + "'"; }

Page 5: Programming WDK Datagrid

In the onInit of the component behavior class, we call the setScrollableResultSet method of the data provider as following: Please note how in the following method when we build up the result set, the column headers used to initialize the TableResultSet have to match the data fields specified in the JSP page:

<dmf:datagrid name="dgCustomList" width="100%"> <dmf:datagridRow> <dmf:datagridRowTd> <dmf:label datafield="r_object_id" /> </dmf:datagridRowTd> <dmf:datagridRowTd> <dmf:label datafield="object_name" /> </dmf:datagridRowTd> <dmf:datagridRowTd> <dmf:label datafield="length_size" /> </dmf:datagridRowTd> <dmf:datagridRowTd> <dmf:label datafield="width_size" /> </dmf:datagridRowTd> <dmf:datagridRowTd> <dmf:label datafield="area" /> </dmf:datagridRowTd> </dmf:datagridRow> </dmf:datagrid>

public void onInit(ArgumentList arg0) { super.onInit(arg0); DfLogger.debug(this, "onInit custom component", null, null); Datagrid dg = (Datagrid) getControl("dgCustomList", Datagrid.class); dg.getDataProvider().setDfSession(getDfSession()); try { ScrollableResultSet rs = buildTableResultSet(getDfSession()); dg.getDataProvider().setScrollableResultSet(rs); } catch (DfException dfe) { // display any possible query errors to the user DfLogger.error(this, "Exception build custom result set," + dfe.getMessage(), null, null);

Page 6: Programming WDK Datagrid

Let us now see how we can further sophisticate our data display using some supporting datagrid controls.

public static ScrollableResultSet buildTableResultSet(IDfSession session) throws DfException { // initialize the table result set using attribute names String[] columnHeaders = new String[] { "r_object_id", "object_name", "length_size", "width_size", "area" }; TableResultSet ts = new TableResultSet(columnHeaders); String dql = "SELECT r_object_id, object_name, " + "length_size, width_size" + " FROM article_document;"; // execute the DQL query and get known attributes IDfCollection rs = null; IDfQuery query = new DfQuery(); query.setDQL(dql); try { rs = query.execute(session, IDfQuery.READ_QUERY); if (rs != null) { while (rs.next()) { // extract the 4 know attribute values from the query String id = rs.getString("r_object_id"); String objectName = rs.getString("object_name"); int length = rs.getInt("length_size"); int width = rs.getInt("width_size"); // now perform some simple calculation for example purposes int area = length * width; // prepare the row that will be added to the result set String[] tableRow = new String[5]; // the order of how the array is initialized is important. // the index has to match the desired columns tableRow[0] = id; tableRow[1] = objectName; tableRow[2] = Integer.toString(length); tableRow[3] = Integer.toString(width); tableRow[4] = Integer.toString(area); // finally, add the row to the table result set ts.add(tableRow); } } } finally { if (rs != null) rs.close(); } return ts; }

Page 7: Programming WDK Datagrid

Supporting datagrid controls Additional WDK controls can be placed inside the datagrid to support the following:

Table headers and footers In plain vanilla HTML, table rows are grouped into a head, foot and body section. The head and foot tags are used to convey information about the data columns. When used, they allow the browsers to support scrolling of data independently of headers and footers. To support table headers and body scrolling within the datagrid, use the datagridth tag and set the datagrid’s fixedheaders attribute to true.

Column Sorting Typically combined with the above table heading tag, we can use datasortlink and datasortimage tags to allow sorting on a specified column. The column attribute simply needs to match the column we want to be sorting on. The tags automatically support the reverse sort as well. The following example shows a datagrid that uses a datasortlink and datasortimage tags placed in a table header:

Data Paging

<dmf:datagrid name="dgCustomList" width="100%" paged="true" fixedheaders="true" > <dmf:datagridTh> <dmf:datasortlink label="Object ID" column="r_object_id" name="objectIdSort" /> </dmf:datagridTh> <dmf:datagridTh> <dmf:datasortimage name='sort1' column="object_name" cssclass='doclistbodyDatasortlink' image='icons/sort/sortByLock.gif' /> </dmf:datagridTh> <dmf:datagridRow> <dmf:datagridRowTd> <dmf:label datafield="r_object_id" /> </dmf:datagridRowTd> <dmf:datagridRowTd> <dmf:label datafield="object_name" /> </dmf:datagridRowTd> <dmf:datagridRowTd> <dmf:label datafield="length_size" /> </dmf:datagridRowTd> <dmf:datagridRowTd> <dmf:label datafield="width_size" /> </dmf:datagridRowTd> </dmf:datagridRow> </dmf:datagrid>

Page 8: Programming WDK Datagrid

When the query results exceed the display area, you must either resort to table body scrolling as describe above, or you can limit the number of results displayed to comfortably view without scrolling via use of paging. The datagrid control enables easy paging through data via use of a datapaging control. You can specify the number of records to display using datapagesize control. The pagesize values attribute can be a comma separated list of values, or it can be read as a standard application preference. See below for an example usage of datapaging.

Row Filtering With the WDK 6.0 release, Documentum introduced a datacolumnbeginswith control used to enable the user to filter the datagrid rows based on specified input. This control renders a textbox which can be used to filter the result based on a specified column. The following example expands on the previous and demonstrates the usage of datapaging, datapagesize and datacolumnbeginswith controls:

Output Formatting Often you need to format the output displayed in the datagrid column. WDK provides numerous out-of-the box formatters that you can use. In the following example, stringlengthformatter is used to limit

<dmf:datagrid name="dgCustomList" width="100%" paged="true"> <dmf:datagridTh> <dmf:datasortlink label="Object ID" column="r_object_id" name="objectIdSort" /> </dmf:datagridTh> <dmf:datagridTh> <dmf:datasortimage name='sort1' column="object_name" cssclass='doclistbodyDatasortlink' image='icons/sort/sortByLock.gif' /> </dmf:datagridTh> <dmf:datagridRow> <dmf:datagridRowTd> <dmf:label datafield="r_object_id" /> </dmf:datagridRowTd> <dmf:datagridRowTd> <dmf:label datafield="object_name" /> </dmf:datagridRowTd> <dmf:datagridRowTd> <dmf:label datafield="length_size" /> </dmf:datagridRowTd> <dmf:datagridRowTd> <dmf:label datafield="width_size" /> </dmf:datagridRowTd> </dmf:datagridRow> <dmf:datapaging name="gridPagers"></dmf:datapaging> <dmf:datapagesize name="pageSize" pagesizevalues="3,5,10"></dmf:datapagesize> <dmf:datacolumnbeginswith name="nameSorter" column="object_name"/> </dmf:datagrid>

Page 9: Programming WDK Datagrid

the number of characters displayed in the object name filed to 5. Please consult Web Development Kit and Webtop Reference Guide for the list of all available formatters.

Developing a custom value formatter By extending the ValueFormatter class, you can easily add support for your custom formatting. In the following example, we are going to develop a custom formatter which will add the text LOW, MEDIUM or HIGH depending on where the value fits in the specified range (cut-offs). Please note that for example purposes we omit some standard control attributes such is id or name – in real world, you should always allow for those attributes. Please consult WDK Development guide for guidelines on developing custom controls. The formatter is used in the JSP page similar to the other formatters:

First, we create the WEB-INF/tdls/customlisting.tld file and define our custom tag as follows:

<dmf:datagridRowTd> <dmf:stringlengthformatter maxlen="5"> <dmf:label datafield="object_name" /> </dmf:stringlengthformatter> </dmf:datagridRowTd>

<dmf:datagridRowTd> <mirza:lowmediumhighformatter highcutoff="100" mediumcutoff="50"> <dmf:label datafield="area" /> </mirza:lowmediumhighformatter> </dmf:datagridRowTd>

Page 10: Programming WDK Datagrid

Our LowMediumHighFormatterTag class implementation looks like the following:

<tag> <name>lowmediumhighformatter</name> <tagclass>com.mirza.wdk.control.LowMediumHighFormatterTag</tagclass> <bodycontent>jsp</bodycontent> <attribute> <name>mediumcutoff</name> <required>true</required> <rtexprvalue>true</rtexprvalue> <description> Specifies the cut-off value for the medium value. Values between mediumcutoff and highcutoff will be display with text Medium </description> </attribute> <attribute> <name>highcutoff</name> <required>true</required> <rtexprvalue>true</rtexprvalue> <description> Specifies the cut-off value for the high value. Values higher than this will be display with the text High. </description> </attribute> </tag>

Page 11: Programming WDK Datagrid

In the LowMediumHighFormatter control class, we are concerned with the implementation of the format method like the following:

package com.mirza.wdk.control; import com.documentum.web.form.Control; import com.documentum.web.form.control.format.ValueFormatterTag; public class LowMediumHighFormatterTag extends ValueFormatterTag { private int mediumcutoff; private int highcutoff; @Override protected Class<? extends Control> getControlClass() { return com.mirza.wdk.control.LowMediumHighFormatter.class; } protected void setControlProperties(Control control) { super.setControlProperties(control); LowMediumHighFormatter formatter = (LowMediumHighFormatter) control; formatter.setMediumcutoff(mediumcutoff); formatter.setHighcutoff(highcutoff); } public int getMediumcutoff() { return mediumcutoff; } public void setMediumcutoff(int mediumcutoff) { this.mediumcutoff = mediumcutoff; } public int getHighcutoff() { return highcutoff; } public void setHighcutoff(int highcutoff) { this.highcutoff = highcutoff; } }

Page 12: Programming WDK Datagrid

To use the custom formatter in our jsp page, remember to import the custom tag library:

Developing custom databound controls One disadvantage of using a TableResultSet as described in one of the previous examples is that the execution of custom processing code (in our case, computation of the area) will happen for every record in the set. This can degrade performance when dealing with large sets of data. Instead, it is much better to custom process the rows only during the rendering. We can do that by writing a custom databound control. In the following example, we will define a custom area control that computes itself using two datafields – length and width. The control is used on the JSP page like the following:

package com.mirza.wdk.control; import com.documentum.web.form.control.format.ValueFormatter; public class LowMediumHighFormatter extends ValueFormatter { private int mediumcutoff; private int highcutoff; public int getMediumcutoff() { return mediumcutoff; } public void setMediumcutoff(int mediumcutoff) { this.mediumcutoff = mediumcutoff; } public int getHighcutoff() { return highcutoff; } public void setHighcutoff(int highcutoff) { this.highcutoff = highcutoff; } public String format(String strValue) { String formattedValue = null; try { int val = Integer.parseInt(strValue); if(val <= getMediumcutoff()) formattedValue = "LOW"; else if (val >= getHighcutoff()) formattedValue = "HIGH"; else formattedValue = "MEDIUM"; } catch(NumberFormatException e) { formattedValue = "INVALID VALUE"; } return formattedValue; } }

<%@ taglib uri="/WEB-INF/tlds/customlisting.tld" prefix="mirza"%>

Page 13: Programming WDK Datagrid

The tag is defined as follows:

Talk DataBoundAreaLabelTag implementation looks like the following:

<dmf:datagridRowTd> <mirza:databoundarealabel lengthdatafield="length_size" widthdatafield="width_size"></mirza:databoundarealabel> </dmf:datagridRowTd>

<tag> <name>databoundarealabel</name> <tagclass>com.mirza.wdk.control.DataBoundAreaLabelTag</tagclass> <bodycontent>jsp</bodycontent> <attribute> <name>widthdatafield</name> <required>true</required> <rtexprvalue>true</rtexprvalue> <description> Specifies the datafield to use when resolving width size. </description> </attribute> <attribute> <name>lengthdatafield</name> <required>true</required> <rtexprvalue>true</rtexprvalue> <description> Specifies the datafield to use when resolving length size. </description> </attribute> </tag>

Page 14: Programming WDK Datagrid

package com.mirza.wdk.control; import java.io.IOException; import javax.servlet.jsp.JspWriter; import com.documentum.web.form.Control; import com.documentum.web.form.ControlTag; public class DataBoundAreaLabelTag extends ControlTag { @Override protected Class<? extends Control> getControlClass() { return com.mirza.wdk.control.DataBoundAreaLabel.class; } protected void setControlProperties(Control control) { super.setControlProperties(control); DataBoundAreaLabel areaLabel = (DataBoundAreaLabel) control; areaLabel.setLengthdatafield(lengthdatafield); areaLabel.setWidthdatafield(widthdatafield); //resolve the actual values from the data provider String length = resolveDatafield(lengthdatafield); String width = resolveDatafield(widthdatafield); //compute the area int area = Integer.parseInt(length) * Integer.parseInt(width); //set on control to be used during rendering areaLabel.setArea(String.valueOf(area)); } protected void renderEnd(JspWriter out) throws IOException { //simply just output the area value. //this is a simplified example for demonstration purposes only DataBoundAreaLabel areaLabel = (DataBoundAreaLabel) getControl(); out.print(areaLabel.getArea()); } private String widthdatafield = null; private String lengthdatafield = null; public String getWidthdatafield() { return widthdatafield; } public void setWidthdatafield(String widthdatafield) { this.widthdatafield = widthdatafield; } public String getLengthdatafield() { return lengthdatafield; } public void setLengthdatafield(String lengthdatafield) { this.lengthdatafield = lengthdatafield; } }

Page 15: Programming WDK Datagrid

The most important happens in the setControlProperties method. The resolveDatafield(String datafieldName) method is provided by WDK framework and is used to extract the value of a specified field from the underlying data provider. The area is then computed and set as a property of the control. This property is later extracted during the rendering. The DataBoundAreaLabel control is a just a POJO with simple getters and setters as follows:

Row selection processing In a common development scenario, besides displaying records, we want to be able to execute some actions on those records. Before we proceed, it is important to describe and note some WDK fundamental concepts. If the action you want to execute fits neatly in the WDK paradigm where documents are listed using a datagrid and actions on the selected documents are performed via the menubar component, then you are interested in the actionmultiselect control. This control was designed specifically to allow for execution of selected datagrid records using WDK-based defined actions (i.e. there exist a corresponding action XML configuration file and the custom action menu item is part of the menubar component). If, on the other hand, your custom component uses a datagrid to allow for custom processing of selected items (via, say a button control), you can use a regular checkbox column and keep track of selected objects using a hidden field and a little bit of JavaScript. Let us first cover the standard WDK approach to processing selected rows. We will later explain how you can get the select object IDs from the datagrid control in your custom component.

package com.mirza.wdk.control; import com.documentum.web.form.Control; public class DataBoundAreaLabel extends Control{ private String widthdatafield = null; private String lengthdatafield = null; private String area = null; public String getArea() { return area; } public void setArea(String area) { this.area = area; } public String getWidthdatafield() { return widthdatafield; } public void setWidthdatafield(String widthdatafield) { this.widthdatafield = widthdatafield; } public String getLengthdatafield() { return lengthdatafield; } public void setLengthdatafield(String lengthdatafield) { this.lengthdatafield = lengthdatafield; } }

Page 16: Programming WDK Datagrid

ActionMultiSelect When the datagrid control is placed inside the actionmultiselect tag, the developer can support row processing by simply adding an actionmultiselectcheckbox column to the datagrid. The framework will automatically enable / disable all menu items depending which rows the user selected and how the actions are configured (i.e. if all required arguments are passed, if the action supports multiselect etc). Additional arguments are passed using the argument tag. For example, the following JSP page renders a selectable datagrid and passes objectId and objectname as arguments to the action menu items:

Please remember that in order for menu items to be dynamically rendered, you must include the dynamicAction.js in your JSP page as follows:

The datagrid control, by its default behavior, allows windows-like left click selection mode for the displayed records. In addition, with this default behavior, the framework enables the right-click context menu as another option for action execution. The datagrid’s rowselection attribute controls this behavior. Setting this attribute to false instructs the datagrid to render a column of checkboxes for selecting records.

Manually getting selected rows in a component class

<dmfx:actionmultiselect name='actionmultiselect'> <dmf:datagrid name="dgCustomList" width="100%"> <dmf:datagridRow> <dmf:datagridRowTd> <dmfx:actionmultiselectcheckbox name='check' value='false'> <dmf:argument name='objectId' datafield='r_object_id' /> <dmf:argument name='objectname' datafield='object_name' /> </dmfx:actionmultiselectcheckbox> <dmf:label datafield="r_object_id" /> </dmf:datagridRowTd> <dmf:datagridRowTd> <dmf:label datafield="object_name" /> </dmf:datagridRowTd> </dmf:datagridRow> </dmf:datagrid> </dmfx:actionmultiselect>

<head> <dmf:webform /> <script language='JavaScript1.2' src='<%=Form.makeUrl(request, "/wdk/include/dynamicAction.js")%>'></script> </head>

Page 17: Programming WDK Datagrid

If your requirements do not fit the WDK model of executing actions, the following example may be useful. This custom component uses a datagrid with a checkbox column and a hidden field to keep track of selected records. The getSelectedItems method simply outputs the selected object IDs. The JSP page looks like following:

The itemSelected event handler is a JavaScript method that keeps tracks of added and removed IDs as follows:

<dmf:form> <dmf:button onclick="displaySelectedIds" nlsid="MSG_GET_SELECTED"></dmf:button> <dmf:datagrid name="dgCustomList" rowselection="false" width="100%"> <dmf:datagridRow> <dmf:datagridRowTd> <dmf:checkbox name='check' value='false' onclick="itemSelected" runatclient="true"> <dmf:argument name='objectId' datafield='r_object_id' /> </dmf:checkbox> <dmf:label datafield="r_object_id" /> </dmf:datagridRowTd> <dmf:datagridRowTd> <dmf:label datafield="object_name" /> </dmf:datagridRowTd> <dmf:datagridRowTd> <dmf:label datafield="length_size" /> </dmf:datagridRowTd> <dmf:datagridRowTd> <dmf:label datafield="width_size" /> </dmf:datagridRowTd> </dmf:datagridRow> </dmf:datagrid> <dmf:hidden id="selectedObjectIds" name="hidden"/> </dmf:form>

Page 18: Programming WDK Datagrid

The displaySelectedIds event handler for the button control retrieves the hidden field and extracts the stored object IDs as follows:

<script> function itemSelected(checkbox, objectId) { //get the old value, if any var hidden = document.getElementById("selectedObjectIds"); var oldValue = hidden.value; //initialize to empty string var newValue = ""; if(checkbox.checked == true) { //add the new value with a separator //skip the separator first time if(oldValue.length == 0) newValue = objectId; else newValue = oldValue + ',' + objectId; } //otherwise, remove it else { var oldValues = oldValue.split(","); for(var i = 0; i < oldValues.length; i++) { if(oldValues[i]==objectId) //removing by ignoring addition for this case else { //skip the separator first time if(newValue.length == 0) newValue = oldValues[i]; else newValue = newValue + "," + oldValues[i]; } } } hidden.value = newValue; } </script>

Page 19: Programming WDK Datagrid

Datagirdrowevent When the rowselection attribute is set to true, Documentum provides additional hook for processing a click on the datagrid row – the datagridrowevent control. This control can be hooked to process either a single select or double click event. The single select event must be processed by the client, while the dblclick can be processed on the server as well. The following example defines a select event and a simple javascript handler to output the object id of the clicked row (NOTE: the datagridrowevent control must be placed inside a datagridrow tag):

<dmf:datagridRowEvent eventname="select" eventhandler="itemSelected" runatclient="true"> <dmf:argument name='objectId' datafield='r_object_id' /> </dmf:datagridRowEvent>

public void displaySelectedIds(Button btn, ArgumentList args) { Hidden hidden = (Hidden)getControl("hidden", Hidden.class); String objectIds = hidden.getValue(); if(objectIds!=null) { String[] ids = objectIds.split(","); if(ids!=null) { for(int i = 0; i < ids.length; i++) { System.out.println("Select ID: " + ids[i]); } } } }

Page 20: Programming WDK Datagrid

The JavaScript event handler is defined as follows:

The dblclick event can be defined and processed on the server. Please note that you can only use one datagridrowevent control inside a datagrid. The event is trapped as follows:

In the component behavior class, the event handler simply outputs the object id of the row that was double-clicked:

<script> function itemSelected(event) { //different processing if multiple rows are selected if (event.count == 1) { //get the clicked id var objectId = event.datagrid.data.getItemActionArgs( event.startIndex, event.type); processSingle(objectId); } else { processMultiple(event); } } function processMultiple(event) { alert('in process multiple, count is: ' + event.count); for(var i = 0; i < event.count; i++) { var objectId = event.datagrid.data.getItemActionArgs(event.startIndex + i, event.type); processSingle(objectId); } } function processSingle(objectId) { alert('in process single, id is: ' + objectId); //rest of your processing here } </script>

<dmf:datagridRowEvent eventname="dblclick" eventhandler="onDoubleClick"> <dmf:argument name='objectId' datafield='r_object_id' /> <dmf:argument name='objectname' datafield='object_name' /> </dmf:datagridRowEvent>

public void onDoubleClick(Control ctrl, ArgumentList args) { String id = args.get("objectId"); System.out.println("onDoubleClick, id = " + id); }

Page 21: Programming WDK Datagrid

Conclusion Datagrid is a type of component that all web applications need to use in one shape or another. If the data can be expressed in terms of rows and columns, that is, in a tabular form, datagrid is ideal for displaying it. Although they are customizable at will, grid controls feature a relatively rigid and inflexible graphical model. The data bound to a datagrid is always rendered like a table, therefore, in terms of rows and columns. It is not possible, for example, to configure datagrid to generate HTML markup that makes no use of tables but resorts to cascading style sheet (CSS) style to define the data layout. The lack of a bidirectional binding, and consequently, an editable version of the datagrid are some of the other disadvantages. Regardless, the WDK datagrid is a very powerful, flexible and most commonly used control and learning to use it properly is a must for any avid WDK developer.

References Web Development Kit and Webtop 6.5 Reference Guide Web Development Kit Development Guide 6.5