0

Listbox/listheader autosort onLoad?

asked 2010-09-10 05:38:11 +0800

vonmc gravatar image vonmc
33 1

Hi,

I have a Listbox defined as this:

	<listbox id="games" multiple="false"  
	 model="@{win$composer.allGames, load-after='convert.onClick, apply.onClick, upload.onUpload'}"  
	 selectedItem="@{win$composer.current}">
	<listhead>
		<listheader label="Game ID" width="110px" sort="auto(gameIDNo)"/>
	</listhead>

...and the sort works fine, when the listheader is clicked, but is there a way of sorting this automatically when the listbox is filled/loaded?
Please notice that it is not filled when the pages first appears, but is filled when convert, apply or upload button has been triggered.

Thanks in advance :)

delete flag offensive retag edit

9 Replies

Sort by ยป oldest newest

answered 2010-09-20 01:38:57 +0800

samchuang gravatar image samchuang
4084 4

Hi

you can sort by your self, before you set into listbox

link publish delete flag offensive edit

answered 2010-09-22 08:05:21 +0800

gul gravatar image gul
22 2

You can also use Listheader.sort(boolean) method.

link publish delete flag offensive edit

answered 2010-10-05 03:58:38 +0800

Matze2 gravatar image Matze2
773 7

Today I faced the same problem described above.
After walking through the code, I found that the most elegant solution is to write a converter for this.

The following converter works for my use case: a listbox, model described by data binding is a List, so the standard coerceToUi method converts it to a ListModelList.
It sorts the model according to the current settings in the ListHeader before setModel is called by the data binding mechanism.

public class SortedListModelConverter extends ListModelConverter {
	private static final long serialVersionUID = 1L;

	@Override
	public Object coerceToUi(Object val, Component comp) {
		Object bean = super.coerceToUi(val, comp);
		
		if (bean instanceof ListModelList && comp instanceof Listbox) {
			Listbox listbox = (Listbox) comp;
			ListModelList model = (ListModelList) bean;
			
			for (Object child : listbox.getListhead().getChildren()) {
				final Listheader hd = (Listheader)child;
				if ("natural".equals(hd.getSortDirection())) {
					continue;
				} else if ("ascending".equals(hd.getSortDirection())) {
					model.sort(hd.getSortAscending(), true);
				} else if ("descending".equals(hd.getSortDirection())) {
					model.sort(hd.getSortDescending(), true);
				}
			}
		}
		
		return bean;
	}
}

In my opinion, ZK should do this automatically. Instead the sort indicators on the list headers are still shown, even if the result is not sorted at all.
But anyway...

link publish delete flag offensive edit

answered 2010-10-06 07:19:04 +0800

samchuang gravatar image samchuang
4084 4

Hi

Here is another way to do it

<?page title="new page title" contentType="text/html;charset=UTF-8"?>
<zk>
<label multiline="true">
	<attribute name="value">
		Demo how to auto sort when user add data to model
	</attribute>
</label>
<zscript><![CDATA[
 import org.zkoss.zk.ui.*;
 import org.zkoss.zk.ui.util.*;
 class Person {
	 String _name;
	 public Person(String name) {
		 _name = name;
	 }
	 public String getName() {
		 return _name;
	 }
 } 

 class MyComposer extends GenericForwardComposer{
	 Listbox lb;
	 Textbox input;
	 AnnotateDataBinder binder;
	 List list = new ArrayList();
	 
	 
	 public void doAfterCompose(Component comp) throws Exception {
		 super.doAfterCompose(comp);
		 
		list = new ArrayList();
		list.add(new Person("Jim"));
		list.add(new Person("Apple"));
		list.add(new Person("Soga"));
		list.add(new Person("Bobo"));
		 
		 //bind all components inside "comp"
		 binder = new AnnotateDataBinder(comp);
		 binder.bindBean("persons", list);
		 binder.loadAll();
	 }
	 
	 public void onClick$btn(Event evt) {
		 String name = input.getValue();
		 if (!"".equals(name)) {
			 list.add(new Person(name));
			 Collections.sort(list, new Comparator() {
				 public int compare(Object o1, Object o2) {
					 Person p1 = (Person)o1;
					 Person p2 = (Person)o2;
					 return p1.getName().compareTo(p2.getName());
				 }
			 });
			 binder.loadAll();
		 }
	 }
 }
]]></zscript>
<window title="new page title" border="normal" apply="MyComposer">
	<listbox id="lb" model="@{persons}" height="200px">
		<listitem self="@{each=entry}">
			<listcell label="@{entry.name}"></listcell>
		</listitem>
	</listbox>
	<textbox id="input"></textbox><button id="btn" label="Add Name"></button>
</window>
</zk>

link publish delete flag offensive edit

answered 2010-10-06 10:15:55 +0800

Matze2 gravatar image Matze2
773 7

Hi samchuang,

my solution covers the case where you have multiple columns in the listbox and you want to control the sort strategy via listheaders.
If the model is filled, then the click on the listheaders does its job.
But if you, e.g. want to refresh your model, you need to prepare the model yourself to be sorted according to the sort indicators in the list headers (which is still active).

In your solution, you fix the sorting in the code ("order by name ascending") for one business object.
My solution works for all business objects, as long as the model is a list (could be easily extended to array or any other list models, of course) and as long the automatic sorting in the list headers worked before.

And, finally, because it is possible to solve this problem in a generic way, I wonder, if ZK itself should not do this.
Or - to not show wrong information - reset the sort state of list headers (which is of course not the favourite solution).

link publish delete flag offensive edit

answered 2010-10-06 10:25:22 +0800

Matze2 gravatar image Matze2
773 7

updated 2010-10-06 10:25:49 +0800

Your example with my converter for illustration (manually edited, not tested):

<window title="new page title" border="normal" apply="MyComposer">
	<listbox id="lb" model="@{persons, converter='matze.SortedListModelConverter', load-after='btn.onclick'"," height="200px">
		<listhead sizable="true">
			<listheader label="Name" sort="auto(name)" />
		</listhead>
		<listitem self="@{each=entry}">
			<listcell label="@{entry.name}"></listcell>
		</listitem>
	</listbox>
	<textbox id="input"></textbox><button id="btn" label="Add Name"></button>
</window>

class MyComposer extends GenericForwardComposer{
	 Textbox input;
	 AnnotateDataBinder binder;
	 List list = new ArrayList();
	 
	 
	 public void doAfterCompose(Component comp) throws Exception {
		 super.doAfterCompose(comp);
		 
		list = new ArrayList();
		list.add(new Person("Jim"));
		list.add(new Person("Apple"));
		list.add(new Person("Soga"));
		list.add(new Person("Bobo"));
		 
		 //bind all components inside "comp"
		 binder = new AnnotateDataBinder(comp);
		 binder.bindBean("persons", list);
		 binder.loadAll();
	 }
	 
	 public void onClick$btn(Event evt) {
		 String name = input.getValue();
		 if (!"".equals(name)) {
			 list.add(new Person(name));
		 }
	 }
 }

link publish delete flag offensive edit

answered 2010-10-10 20:50:11 +0800

samchuang gravatar image samchuang
4084 4

@Matze2

Thanks for your sample code, indeed, I didn't handle sort from listheader, thanks for your code

link publish delete flag offensive edit

answered 2013-02-01 03:14:08 +0800

f066457 gravatar image f066457
0

Hello,

Here is the solution : http://books.zkoss.org/wiki/ZK_Configuration_Reference/zk.xml/The_Library_Properties/org.zkoss.zul.listbox.autoSort (http://books.zkoss.org/wiki/ZKConfigurationReference/zk.xml/TheLibraryProperties/org.zkoss.zul.listbox.autoSort)

link publish delete flag offensive edit

answered 2014-04-22 17:54:46 +0800

JMVAZ gravatar image JMVAZ
13 3

updated 2014-04-22 17:56:34 +0800

Just to add one working solution.

<listheader label="Game ID" width="110px" sort="auto(gameIDNo)" onCreate="self.sort(true)"/>

The API: http://www.zkoss.org/javadoc/7.0.1/zk/org/zkoss/zul/Listheader.html#sort(boolean)

link publish delete flag offensive edit
Your reply
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!

[hide preview]

Question tools

Follow

RSS

Stats

Asked: 2010-09-10 05:38:11 +0800

Seen: 1,415 times

Last updated: Apr 22 '14

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More