cancel
Showing results for 
Search instead for 
Did you mean: 

Table Filter class cannot filter?

Former Member
0 Kudos

I tried to implement the Table Filter function in Kapil Kample Blog: /people/kapil.kamble/blog/2006/12/21/how-to-get-ready-made-filter-for-your-web-dynpro-table-with-minimal-coding

After I follow every steps in the blog (In fact, the blog is not explaining step by step from the beginning, that is why I am afraid I may still miss something).

I got the filter row right below the Column filter, and I have the filter field enterable in Color column. When I enter some filter text, said: "red". It does not really filter the list, the default elements still stay there (it is not filtered, still 25 elements there).

But the debugger shown that it really went through the filter method and return the list.

I don't know what went wrong here. Here are some steps I did:

I created a TableProducts node (the filtered list that display ion table), OriginalProducts node (the node that contains all element), FilterProducts node (node contains elements to be filtered).

I set the FilterProducts node as:

Cardinality = 1:1

InitializedLeadSelection= true

It contains node attribute:

Color:

Type = string

I mapped it to the Table Column of Color:

filterValue = FilterProducts.Color

I set the Table (Id = ShoppingBasket):

Event -> onFilter = Filter

In TableFilterView,

Here is the Filter action implementation :

public void onActionFilter(com.sap.tc.webdynpro.progmodel.api.IWDCustomEvent wdEvent )

{

//@@begin onActionFilter(ServerEvent)

wdContext.currentContextElement().getTableFilter().filter(wdEvent,wdContext.nodeTableProducts(),wdContext.nodeProducts(),

wdContext.nodeFilterProducts());

//@@end

}

and the wdDoModifyView method:

public static void wdDoModifyView(IPrivateTableFilterView wdThis, IPrivateTableFilterView.IContextNode wdContext, com.sap.tc.webdynpro.progmodel.api.IWDView view, boolean firstTime)

{

//@@begin wdDoModifyView

if ( firstTime )

{

if ( null != view )

{

IWDTable table = (IWDTable) view.getElement("ShoppingTable");

wdContext.currentContextElement().setTableFilter(new TableFilter(table,wdThis.wdGetFilterAction()));

}

}

//@@end

}

HERE IS SOEMTHING I AM NOT SURE: Should I copy all the elements from nodeProducts (original) to nodeTableProducts in the init () method:

As if I don't do so, the nodeTableProducts is empty when the application start. That is why I do this:

public void wdDoInit()

{

//@@begin wdDoInit()

WDCopyService.copySubtree((IWDNode)wdContext.nodeProducts(),(IWDNode)wdContext.nodeTableProducts());

//@@end

}

I thought I don't have to populate the nodeTableProducts, the TableFilter constructor will do it.

But this is not mentioned in Kapil blog.

I checked the Table Filter class. in the contructors:

public TableFilter(IWDTable table, IWDAction filterAction)

{

this.table = table;

// sanity checks

if (filterAction == null)

throw new IllegalArgumentException("Filter action must be given");

if (table == null)

throw new IllegalArgumentException("Table must be given");

if (table.bindingOfDataSource() == null)

throw new IllegalArgumentException("Data source of table with id '" + table.getId() + "' must be bound");

String dataSourcePrefix = table.bindingOfDataSource() + ".";

int index = 0;

for (Iterator it = table.iterateColumns(); it.hasNext(); ++index)

{

// for every column: try to make it bindable

IWDTableColumn column = (IWDTableColumn) it.next();

// attribute must be determined

String bindingOfPrimaryProperty = bindingOfPrimaryProperty(column.getTableCellEditor());

if ( bindingOfPrimaryProperty == null

|| !bindingOfPrimaryProperty.startsWith(dataSourcePrefix) )

continue; // no attribute found or outside of data source

String attributeName = bindingOfPrimaryProperty.substring(dataSourcePrefix.length());

if (attributeName.indexOf('.') >= 0)

continue; // attribute not immediately below data source

table.setOnFilter(filterAction);

}

}

It does not really copy the elements from nodeProducts to nodeTableProudcts.

But in the filter method it does:

/**

  • This method must be called from the event handler of this table filter's

  • filter action. It performs the actual filter operation.

*/

public void filter(IWDCustomEvent wdEvent,IWDNode dataSource, IWDNode originalSource, IWDNode filterNode)

{

// find the things we need

String refinedFilter = null;

String field = null;

String attributeName = null;

String bindingOfPrimaryProperty = null;

String dataSourcePrefix = table.bindingOfDataSource() + ".";

IWDTableColumn[] columns = table.getColumns();

String path = null;

String attribute = null;

StringTokenizer tokenizer = null;

dataSource.invalidate();

WDCopyService.copyElements(originalSource,dataSource);

int totalElements = originalSource.size();

for(int i = totalElements - 1; i >= 0 ; i--)

{

IWDNodeElement element = dataSource.getElementAt(i);

for(int j =0; j < columns.length; j++ )

{

IWDTableColumn colmn = columns[j];

bindingOfPrimaryProperty = bindingOfPrimaryProperty(colmn.getTableCellEditor());

if(bindingOfPrimaryProperty != null

&& bindingOfPrimaryProperty.startsWith(dataSourcePrefix))

attributeName = bindingOfPrimaryProperty.substring(dataSourcePrefix.length());

if(attributeName.indexOf('.') < 0)

field = element.getAttributeAsText(attributeName);

if(colmn.bindingOfFilterValue() != null)

{

path = colmn.bindingOfFilterValue();

tokenizer = new StringTokenizer(path, ".");

while(tokenizer.hasMoreTokens())

{

attribute = tokenizer.nextToken();

}

refinedFilter = refineFilterString(filterNode.getCurrentElement().getAttributeAsText(attribute));

if(!(field.matches(refinedFilter)))

{

dataSource.removeElement(element);

}

else

{

// remove icon of previously filtered column

if ( currentlyFilteredColumn != null

&& currentlyFilteredColumn.getHeader() != null )

currentlyFilteredColumn.getHeader().setImageSource(null);

currentlyFilteredColumn = columns[j];

if ((currentlyFilteredColumn.getHeader() != null) && (dataSource.size() != originalSource.size()))

currentlyFilteredColumn.getHeader().setImageSource("~sapicons/s_b_filt.GIF");

}

}

}

}

}

Please advise.

Thanks.

Kent

Accepted Solutions (1)

Accepted Solutions (1)

Former Member
0 Kudos

I did a testing on this:

I create a table that binded to the nodeProducts (original), and another table below that binded to the nodeTableProducts.

So now, the nodeProducts table (said OriginalTable) contains all the elements (25), and the nodeTableProducts (said FilteredTable) is empty.

I do the filter function on the OriginalTable. When I entered "red" on Color column, it trigger the filter method.

Now, the FilteredTable display all the elements contains "red" in the Color columns (said there are 5 elements).

But the OriginalTable remains all elements (25).

Seems like the filter method works fine.

But why it does not work when I do the filter function from the FilteredTable (that copy all elements from nodeProducts), like I mentioned in my first message.

Thanks for help in advance.

Kent

Former Member
0 Kudos

I ran the debugger, I found out that it never run into this for loop in the filter method:

for(int j =0; j < columns.length; j++ )

{

IWDTableColumn colmn = columns[j];

bindingOfPrimaryProperty = bindingOfPrimaryProperty(colmn.getTableCellEditor());

if(bindingOfPrimaryProperty != null

&& bindingOfPrimaryProperty.startsWith(dataSourcePrefix))

attributeName = bindingOfPrimaryProperty.substring(dataSourcePrefix.length());

if(attributeName.indexOf('.') < 0)

field = element.getAttributeAsText(attributeName);

if(colmn.bindingOfFilterValue() != null)

{

path = colmn.bindingOfFilterValue();

tokenizer = new StringTokenizer(path, ".");

while(tokenizer.hasMoreTokens())

{

attribute = tokenizer.nextToken();

}

refinedFilter = refineFilterString(filterNode.getCurrentElement().getAttributeAsText(attribute));

if(!(field.matches(refinedFilter)))

{

dataSource.removeElement(element);

}

else

{

// remove icon of previously filtered column

if ( currentlyFilteredColumn != null

&& currentlyFilteredColumn.getHeader() != null )

currentlyFilteredColumn.getHeader().setImageSource(null);

currentlyFilteredColumn = columns[j];

if ((currentlyFilteredColumn.getHeader() != null) && (dataSource.size() != originalSource.size()))

currentlyFilteredColumn.getHeader().setImageSource("~sapicons/s_b_filt.GIF");

}

}

}

Seems like the columns.length is equal to "0" all the time.

Just don't know why?

former_member182372
Active Contributor
0 Kudos

Kent, try to use iterateGroupedColumns instead of iterateColumns in TableFilter constructor.

Former Member
0 Kudos

I saw that all my columns in the FilterTable are GroupedColumns.

How come when I use the "Apply Temple" -> "Table", it will automatically build the Table with GroupedColumn insteads of Column.

I read the API Docs stated that:

The TableColumnGroup allows yout to combine several columns and give them one common heading. Into a TableColumnGroup, you can insert TableColumns or other TableColumnGroups.

I only find TableColumnGroup , but I can't find anything on TableGroupedColumn. I am not sure they are the same thing?

In the Layout View, the Table UI stated that it is type of "GroupedColumn".

Can you explain and provide me more information on this (GroupedColumn)?

Thanks for your help.

Kent

Former Member
0 Kudos

Maksim,

I replaced all the GroupedColumns with Columns. Now, the filter function works.

But I want to edited the code to work for GroupedColumns and Columns too.

I replaced the following codes to test with the GroupedColumn.

//IWDTableColumn[] columns = table.getColumns();

IWDAbstractTableColumn[] columns = table.getGroupedColumns();

//IWDTableColumn colmn = columns[j];

IWDAbstractTableColumn colmn = columns[j];

(I can't really find a class with the name : IWDGroupedTableColumn)

And the IWDAbstractTableColumn doesn't really have methods for:

colmn.getTableCellEditor();

colmn.bindingOfFilterValue();

Please advise.

Thanks.

Kent

former_member182372
Active Contributor
0 Kudos

Kent, groupedColumns aggregation is just term but not actual java class name or name of UI element. groupedColumns aggregation includes <a href="https://help.sap.com/javadocs/NW04S/current/wd/com/sap/tc/webdynpro/clientserver/uielib/standard/api/IWDAbstractTableColumn.html">IWDAbstractTableColumn</a> instances.

former_member182372
Active Contributor
0 Kudos

Kent, see commnets of Andrew Crawley on original blog (/people/kapil.kamble/blog/2006/12/21/how-to-get-ready-made-filter-for-your-web-dynpro-table-with-minimal-coding) with version for 04s.

Former Member
0 Kudos

Maksim,

I solved the problem form the hints in Andrew comments on the blog. I made some modification from the original instead of following Andrew modified code, as I don't know why he put two for loop to process the columns, where we can do it once.

But now, I found out that this TableFilter class only able to filter with string type, which cannot filter Date, decimal and etc very well.

I found a new blog which do so:

/people/peter.vignet/blog/2007/01/03/generic-web-dynpro-java-table-filter

This TableFilter class can filter ever Icon.

Again, I am having some error with this, and this is slightly complicated.

I will open another thread for this one. I am not sure you looked at that before. Hope I can get some help from you on this too.

Thanks for your help again.

Kent

Former Member
0 Kudos

Maksim, I figured out what causes the problem now (for another TableFilter).

It was the null value passed in for the HashTable.

public static void wdDoModifyView(IPrivateTableFilterView wdThis, IPrivateTableFilterView.IContextNode wdContext, com.sap.tc.webdynpro.progmodel.api.IWDView view, boolean firstTime)

{

//@@begin wdDoModifyView

if (firstTime ) {

IWDTable table = (IWDTable) view.getElement("ShoppingBasket");

//wdContext.currentContextElement().setGenericTableFilter(

// new GenericTableFilter(table, //wdThis.wdGetGenericTableFilterAction(),wdContext.nodeProducts(),null));

wdContext.currentContextElement().setGenericTableFilter(

new GenericTableFilter(table, wdThis.wdGetGenericTableFilterAction(),wdContext.nodeProducts(),new Hashtable()));

}

Insteads of passing null, pass a new HashTable.

Answers (0)