-
FEATURED COMPONENTS
First time here? Check out the FAQ!
I use a grid with
<column label="name" sort="auto(name)" />
But unfortunately the automatic sorting is case sensitive (see http://forum.zkoss.org/question/78175/zk-listbox-auto-sorting-by-pojo-without-using-any-comparator/).
As a workaround to the above problem I would like to push my own "default comparators". I did not find any hints here: http://books.zkoss.org/wiki/ZK%20Configuration%20Reference/zk.xml/The%20Library%20Properties (Library Properties).
Thanks to samchuang's hints I was able to roll my own workaround. Here my (hackish) solution.
Note that I plan to extend this for property "paths" (e.g. "bean.property1.property2"), but at the moment it only works for simple "one-level" properties. Also note that the current version cannot handle null-entities or null-properties.
I defined a language addon (as suggested by samchuang):
<language-addon>
<addon-name>MyColumn</addon-name>
<language-name>xul/html</language-name>
<component>
<component-name>column</component-name>
<extends>column</extends>
<component-class>mypackage.MyColumn</component-class>
</component>
</language-addon>
The implementation of MyColumn:
public class MyColumn extends Column
{
@SuppressWarnings("unused")
private static final Logger LOGGER = Logger.getLogger(IbrLimsColumn.class.getName());
public MyColumn()
{
}
@Override
public void setSort(String type) throws ClassNotFoundException, InstantiationException, IllegalAccessException
{
if(type.startsWith("str"))
{
String propertyName = type.substring("str(".length(), type.length() - 1);
setSortAscending(new StringPropertyComparator(propertyName, true));
setSortDescending(new StringPropertyComparator(propertyName, false));
}
else
{
super.setSort(type);
}
}
}
The usage:
<grid model="@load(vm.employees)" sizedByContent="true">
<columns sizable="true" menupopup="auto">
<column label="Last name" sort="str(lastName)" />
<column label="First name" sort="str(firstName)" />
</columns>
<template name="model">
<row>
<a href="/Employee.zul?id=${each.id}">${each.lastName}</a>
<label value="${each.firstName}" />
</row>
</template>
</grid>
And finally the heart of the implementation, the StringPropertyComparator:
public class StringPropertyComparator implements Comparator<Object>
{
private final boolean m_ascending;
private final String m_propertyPath;
private Method m_getter = null;
private Comparator m_comparator = null;
public StringPropertyComparator(String propertyPath, boolean ascending)
{
m_propertyPath = propertyPath;
m_ascending = ascending;
}
@Override
public int compare(Object entity1, Object entity2)
{
try
{
return compare0(entity1, entity2);
}
catch(Throwable t)
{
throw new RuntimeException("unexpected", t);
}
}
private int compare0(Object entity1, Object entity2) throws Exception
{
if(m_getter == null)
{
m_getter = ReflectionTools.getGetterMethod(entity1, m_propertyPath);
}
if(m_comparator == null)
{
// determine comparator based on property type
Collator collator = Collator.getInstance(new Locale("en", "US"));
// sort A, a, Ä, ä, Â, â, À, à (and other accents) at the same position in the list
collator.setStrength(Collator.PRIMARY);
m_comparator = collator;
}
Object value1 = m_getter.invoke(entity1);
Object value2 = m_getter.invoke(entity2);
if(m_ascending)
{
return m_comparator.compare(value1, value2);
}
else
{
return -m_comparator.compare(value1, value2);
}
}
}
And the ReflectionTools:
public class ReflectionTools
{
public static Method getGetterMethod(Object bean, String propertyName)
{
Class<?> beanClass = bean.getClass();
try
{
return beanClass.getMethod(getGetterName(propertyName));
}
catch(Throwable t)
{
// ignore
}
try
{
return beanClass.getMethod(getBooleanGetterName(propertyName));
}
catch(Throwable t)
{
// ignore
}
throw new IllegalArgumentException("not getter method found for '" + propertyName + "', bean: " + bean);
}
public static String getGetterName(String propertyName)
{
String getterName = "get" + capitalizeFirstLetter(propertyName);
return getterName;
}
public static String getBooleanGetterName(String propertyName)
{
String getterName = "is" + capitalizeFirstLetter(propertyName);
return getterName;
}
private static String capitalizeFirstLetter(String string)
{
String result = string.substring(0, 1).toUpperCase() + string.substring(1, string.length());
return result;
}
}
Hi, you can implement it easily by
define the MyColumn as a component in lang-addon.xml
<component>
<component-name>column</component-name>
<extends>column</extends>
<component-class>test.MyColumn</component-class>
</component>
you can also refer to The language-addon
Take a look Here you can write your own comparator this example will help you to overcome your issue.
Asked: 2013-02-01 15:42:15 +0800
Seen: 34 times
Last updated: Feb 05 '13
dude try this link i think its helpful
http://www.zkoss.org/zkdemo/listbox/sort_by_comparator?search=compara (ZK Comparator)
good luck
kazma ( 2013-02-04 19:35:34 +0800 )edit