Generic Web Dynpro Java table filter

Want a SAP Web Dynpro filtering tool that's as easy to implement and to use as the Table Sorter Java Class? This article by Peter Vignet, reposted from SDN, provides such a tool.

Generic Web Dynpro Java Table filter Web Dynpro Table offers a Table Sorter Java class that can be used directly with very few lines of coding to sort any table. It is powerful tool that is easy to implement and use. Web Dynpro Table offers also a filtering possibility through the filtering row. The Filtering row is the first row and only the UI is provided; the filtering action is not.

The logic of the filter process is not implemented in Web Dynpro. The application developer must implement the filtering action to be executed (see SAP UI Web Dynpro Table documentation). The Java class described below offers a filtering tool that is as easy to implement and to use as the Table Sorter Java Class.

Table filter
The Java Web Dynpro TableFilter is a Java class. It filters the column of a table according the filter value located at the top of a column. It can be implemented in few steps. Figure 1:

Here is an example of filtering using the TableFilter java class. Figure 2:

When the TableFilter’s filter action is triggered, the filter method passes two nodes. The first node contains all the data and the table’s node, the node that shows the data. The TableFilter populates the table node from the all data node according the filter values. Filtering is done for each filter value of each column; only the row matching all the filters are shown.

Filtering capabilities:
The table filter has the following capabilities:
Strings: if the filter value is a “a” it returns any fields that as a “a” whatever is in the position of the a in the string and it does not makes difference between uppercase and lowercase. It also accepts the # (exclude) or (=) include sign in first position.
Numeric values, dates, times: It filters for the exact value, a range(~), include(=), exclude(#) sign. The include or exclude sign should be in first position.
For range “~100”, gives the values up to 100 included;”1~100” gives all values between 1 and 100, 1 and 100 included;” 100~” gives all the values about 100 , 100 included
Boolean values: Booleans can be filtered using include (=) or exclude (#).
Icons: Icons can be filtered according their legends. Legend is language dependent. Icon legends can be shown as a tool tip of the icon.

Quick steps for default implementation:
First we will speak about the quick default implementation. Then we will see how we can improve the default implementation. The default implementation assumes that the table node is a value node and dropdown and icons, if any, in the table are not filtered and no columns are update-able.

Step 1: Add TableFilter 

Add the table filter to the package. Figure 3:

Step 2: Create nodes

The filter table needs three nodes (see Figure 4 below): One table node, one filter node and one all data node. All these nodes should be under the root node context. The all data node contains always all the data; it is called in the figure below “sourceNode” . The “FilterNode” contains the filter values. The attributes of the SourceNode and TableNode are identical. They have the same attribute names and the attributes with the same name are of the same type. The FilterNode is of cardinality 1,1 and contains the values of the filter; one attribute per column you want to filter. All the filter attributes are of type string. Figure 4:


Step 3: Associate filter to column

Each column that you want to filter must have a filter. Figure 5:


Step 4: Create Table Filter in context view

In the view controller, create a context attribute “TableFilter” . Its type is TableFilter. Figure 6:

The details steps to do it are :
The type is chosen by selecting the “…” button . Figure 7:

Then select button Java Native Type & Browse button. Figure 8:


Step 5: Create filter action

Go to the Actions tab and create an action with the name filter. Figure 9:


Step 6: Code Filter action

Go to the implementation tab and under the onActionFilter(), put the following code:
public void onActionfilter(com.sap.tc.webdynpro.progmodel.api.IWDCustomEvent wdEvent ) {
//@@begin onActionfilter(ServerEvent)
wdContext.currentContextElement().getTableFilter().filter(wdContext.nodeSource(), wdContext.nodeTable());

Step 7: Code wdDoModifyView

Switch to the method wdDoModifyView and enter the following source code:
public static void wdDoModifyView(IPrivateTableFilterCV wdThis, IPrivateTableFilterCV.IContextNode wdContext, com.sap.tc.webdynpro.progmodel.api.IWDView view, boolean firstTime) {
//@@begin wdDoModifyView
if (firstTime ) {
IWDTable table = (IWDTable) view.getElement("Table");
wdContext.currentContextElement().setTableFilter( new TableFilter(table, wdThis.wdGetFilterAction(), wdContext.nodeSource(),null));

“Table” is the id of the UI table. Figure 10:

At the first instance of wdDoModifyView, initialize the table filter. The constructor of the table filter for each column finds the associated filter and the needed comparator to perform the column filtering.

Step 8: Add explanation:

Add an explanation of the filter’s capabilities above your table. Figure 11:

The text could be like this: Character fields are filtered for any character in the field, include =, exclude #. Numeric, Date fields can be filtered for exact value, range ~ , exclude # ; Check boxes can be filtered for include = or exclude #; Icon by legend.

Improving the default implementation:
The default implementation can be improved to filter icons, dropdown and update the All data node if the table has been updated or if the table had some rows that have been added or deleted.

Filtering icons

A icon is filtered according its legend. You need, in the all data node and the table node, an attribute for the legend icons (legend icon are language dependent and will have to be translated), so in the TableFilter constructor the last parameter is a hashtable that indicates the mapping between the icon column ids and the icon legend attribute.
The constructor becomes:
if (firstTime ) {
// mapping of the icon column to the legend column{
Hashtable hash=new Hashtable(); hash.put("Icon","IconLegend");
// table constructor has the hash table as a parameter
IWDTable table = (IWDTable) view.getElement("Table");
wdContext.currentContextElement().setTableFilter( wdContext.currentContextElement().setTableFilter( new TableFilter(table, wdThis.wdGetFilterAction(), (IWDNode)wdContext.nodeSource(),hash));

The logic is explained by figures 12 and 13. Figure 12:

Figure 13:

The result is Figure 14:


Warning: Never make a column legendIcon in the table. The reason is because initialization of the TableFilter will automatically associate the legendIcon column with the legendIcon attribute. The icon mapping given by the hashtable will be disregarded. Figure 15:

Filtering dropdown:

Since the dropdown shows text but the column value is a key, the filtering must be done the same way the icon filtering is done. This means that at the initialization, the hashtable indicates a mapping between the dropdown column and the node attribute to filter. In our example, the column shown is owner, but the filtering is done on the attribute ownertext.

Updating the “All Data Node” from the Table Node

Default implementation does not update the All Data Node. If the table is update-able, and some data are updated, or some rows are added or deleted, the TableFilter does not update the All Data Node, the “sourceNode” in our example. The DC has to do the update if the default implementation is used as is, as explained by the Figure 16:

If the table has been updated or if some rows have been added or deleted, the All Data Node needs to be updated from the table node. TableFilter has currently two methods that are doing that. To update the “All Data Node” from the Table Node, each method has to know what attribute is the unique identifier of the element (this identifier cannot be the element index because it will not work in case of deleting and adding rows). Figure 17 shows an attribute “Row Unique ID” that uniquely identifies an element

The method to update is:

public void updateAllDataNodeElment( IWDNode sourceNode, IWDNode targetNode, String attributeRowId, boolean addRowOnFly);

String attributeRowId: is the attribute name that uniquely identifies the row; this attribute is of type String.
Boolean addRowonFly: if a row has been added in the table, not only the updated existing row will be updated in AllDataNode but if a row has been created, if the flag is set to true, a new element is created in the AllDataNode.
The method to delete is:

public void deleteAllDataNodeElement(IWDNode sourceNode, IWDNode targetNode, String attributeRowId, ArrayList idsToDelete)
String attributeRowId is the attribute name that uniquely identifies the row; this attribute is of type String.
ArrayList idsToDelete: contains a list of the unique row identifier to delete.

Coming back to our example, the table has now three buttons “Update”,“Add “ & “Delete ” for adding or deleting a row.
First we update the first row; we change the integer column from 1000 to 1. By pressing the button update and directly invoking the method updateAllDataNodeElment, the all data node is updated and so the table can be filtered and this new value will be taken into account. Figure 18:

If we have dropdowns to update before invoking the updateAllDataNodeElment method, the table attribute “Ownertext” should be updated accordingly. Figure 19:


Continuing with our example, using the button “Add” adds a new row to the table, the “Add” button action invokes at the end the updateAllDataNodeElment with the boolean addRowOnFly= true that update the all data node .Figure 20 shows that a new row has been added at the end of the table:

Since the all data node has been updated, a new filtering takes into account the new row. Figure 21:


Inversely, by selecting motile rows and pressing the “Delete “ button the deleteAllDataNodeElement method is invoked and the rows are deleted from the table node and the All Data Node. Figure 22:

So the next filtering will be accurate and will take into account the fact that some rows have been deleted. Figure 23:


Tips and trick:
If the data of the AllDataNode are not changed:
If you initiate the TableFilter with the AllDataNode fully populated and the data are not changed, when using the filter action, you can pass a null instead of a the AllDataNode and the method will retrieve the data from the AllDataNode you pass at the initialization. Or the last time you passed it through the filter action.


TableFilter Class Code

Peter Vignet joined SAP Labs, Palo Alto, as a senior developer in 2001 for WebDynpro Composite Applications on NetWeaver platform.


This content is reposted from the SAP Developer Network.
Copyright 2007, SAP Developer Network

SAP Developer Network (SDN) is an active online community where ABAP, Java, .NET, and other cutting-edge technologies converge to form a resource and collaboration channel for SAP developers, consultants, integrators, and business analysts. SDN hosts a technical library, expert blogs, exclusive downloads and code samples, an extensive eLearning catalog, and active, moderated discussion forums. SDN membership is free.

Want to read more from this author? Click here to read Peter Vignet's weblog. Click here to read more about Web Dynpro on SDN.


Dig Deeper on SAP integration