0

How to change page on listbox after changing selection?

asked 2012-08-06 22:54:50 +0800

iwagner gravatar image iwagner
45

In my zul file I have something like this:

<listbox id="mylist" autopaging="true" mold="paging">
    <listhead>
        <listheader label="Name"/>
        <listheader label="Value"/>
    </listhead>
    <template name="model">
        <listitem>
            <listcell label="${each.name}"/>
            <listcell label="${each.value}"/>
        </listitem>
    </template>
</listbox>

Then, in my Java I have something like this:

@Wire("#mylist")
private Listbox mylist;
private ListModelList<NameValuePair> myDataList = new ListModelList<NameValuePair>();

public void doAfterCompose(Component component) throws Exception {
    super.doAfterCompose(component);
    mylist.setModel(myDataList);
    populateDataList();  // Get's data out of a database and populates the myDataList object
}

That works just fine and the data gets displayed properly. However, I have a button on that page and as part of the event action I need to change the selected item in the list. So, I tried something like this:

NameValuePair nvp = new NameValuePair();
nvp.setName("user");
nvp.setValue("test");
Set<NameValuePair> selection = new HashSet<NameValuePair>();
selection.add(nvp);
myDataList.setSelection(selection);

There are two problems that I'm having. First, after I call setSelection() the list is not updated and the chosen row is not actually shown as selected. Second, when I select a row that is on a different page (the page mold is turned on) I would expect the active page to change to the same page as the newly selected item. However, that is not the case. How do I accomplish what I am trying to do? In a nutshell I want to have some way through my program to select an item in the list and have the page change (or the list scroll) to wherever the new selection is.

Thanks,

Isaac

delete flag offensive retag edit

11 Replies

Sort by ยป oldest newest

answered 2012-08-06 23:59:48 +0800

jj gravatar image jj
638 3

You can call myList.setModel(myDataList) again, which will update the view.
Don't think it will go to selection page automatically, you may have to set the active page yourself correctly.

link publish delete flag offensive edit

answered 2012-08-07 13:41:19 +0800

iwagner gravatar image iwagner
45

I will try that, but it seems like this should be part of the API.

link publish delete flag offensive edit

answered 2012-08-07 14:23:13 +0800

iwagner gravatar image iwagner
45

Hmmm.... That didn't work. Not sure what to try next.

link publish delete flag offensive edit

answered 2012-08-16 12:31:53 +0800

sjoshi gravatar image sjoshi flag of India
3493 1 8
http://zkframeworkhint.bl...

You can Use NotifyChange("Give ur list Varaible")

link publish delete flag offensive edit

answered 2012-08-17 09:09:03 +0800

benbai gravatar image benbai
2228 6
http://www.zkoss.org

Hi Isaac,

Please try Listbox#addItemToSelection(Listitem), for example,

<zk>
	<zscript><![CDATA[
		import java.util.*;

		import org.zkoss.zul.ListModelList;
		class ItemData {
			String _firstName;
			String _lastName;
			public ItemData (String firstName, String lastName) {
				_firstName = firstName;
				_lastName = lastName;
			}
			public void setFirstName (String firstName) {
				_firstName = firstName;
			}
			public String getFirstName () {
				return _firstName;
			}
			public void setLastName (String lastName) {
				_lastName = lastName;
			}
			public String getLastName () {
				return _lastName;
			}
		}
		List dataList = new ArrayList();
		dataList.add(new ItemData("fOne", "lOne"));
		dataList.add(new ItemData("fTwo", "lTwo"));
		dataList.add(new ItemData("fThree", "lThree"));

		ListModelList model = new ListModelList(dataList);
	]]></zscript>
    <listbox id="lb" model="${model}">
    	<template name="model">
	        <listitem>
	            <listcell label="${each.firstName}"/>
	            <listcell label="${each.lastName}"/>
	        </listitem>
	    </template>
    </listbox>

	<button label="test">
		<attribute name="onClick"><![CDATA[
			import org.zkoss.zul.ext.Selectable;
			for (Listitem li : lb.getItems()) {
				ItemData d = (ItemData)li.getValue();
				if ("fTwo".equals(d.getFirstName())
					&& "lTwo".equals(d.getLastName())) {
					lb.addItemToSelection(li);
					break;
				}
			}
		]]></attribute>
	</button>
</zk>

Regards,
Ben

link publish delete flag offensive edit

answered 2012-08-20 14:50:22 +0800

iwagner gravatar image iwagner
45

I'm sure that would work, but that solution requires iterating over every item in the list until you find the one that matches. I've got a live data source with hundreds of millions of records, so that is entirely impractical.

link publish delete flag offensive edit

answered 2012-08-20 17:46:19 +0800

jj gravatar image jj
638 3

This piece of code is suspicious in your original posting:

NameValuePair nvp = new NameValuePair();
nvp.setName("user");
nvp.setValue("test");
Set<NameValuePair> selection = new HashSet<NameValuePair>();
selection.add(nvp);
myDataList.setSelection(selection);

You are creating new objects, and then call setSelection on the model. Nothing would be selected, because the new objects are NOT in the model.
You should find the object in your model that you want to be selected.

link publish delete flag offensive edit

answered 2012-08-21 06:32:44 +0800

benbai gravatar image benbai
2228 6
http://www.zkoss.org

Hi Isaac,

You can try use ListitemRenderer and record Listitems in a HashMap:

<zk>
	<zscript><![CDATA[
		import java.util.*;

		import org.zkoss.zul.ListModelList;
		import org.zkoss.zul.ListitemRenderer;
		import org.zkoss.zul.Listitem;
		import org.zkoss.zul.Listcell;

		Map itemMap = new HashMap();
		class ItemData {
			String _firstName;
			String _lastName;
			public ItemData (String firstName, String lastName) {
				_firstName = firstName;
				_lastName = lastName;
			}
			public void setFirstName (String firstName) {
				_firstName = firstName;
			}
			public String getFirstName () {
				return _firstName;
			}
			public void setLastName (String lastName) {
				_lastName = lastName;
			}
			public String getLastName () {
				return _lastName;
			}
		}
		List dataList = new ArrayList();
		dataList.add(new ItemData("fOne", "lOne"));
		dataList.add(new ItemData("fTwo", "lTwo"));
		dataList.add(new ItemData("fThree", "lThree"));

		ListModelList model = new ListModelList(dataList);
		ListitemRenderer renderer = new ListitemRenderer() {
			public void render(Listitem item,
		            Object data,
		            int index) throws Exception {
				ItemData idata = (ItemData)data;
				new Listcell(idata.getFirstName()).setParent(item);
				new Listcell(idata.getLastName()).setParent(item);
				itemMap.put(idata.getFirstName()+"_"+idata.getLastName(), item);
			}

		}
	]]></zscript>
    <listbox id="lb" model="${model}" itemRenderer="${renderer}" />

	<button label="test">
		<attribute name="onClick"><![CDATA[
			import org.zkoss.zul.ext.Selectable;
			lb.addItemToSelection(itemMap.get("fTwo_lTwo"));
		]]></attribute>
	</button>
</zk>

Regards,
Ben

link publish delete flag offensive edit

answered 2012-08-27 19:58:33 +0800

iwagner gravatar image iwagner
45

I appreciate all the input. The problem still remains of how to alter the selection without keeping a copy of the data in memory. I am using this pattern for my page so that only a small portion of data is in memory at once: http://books.zkoss.org/wiki/ZK%20Developer%27s%20Reference/Performance%20Tips/Listbox,%20Grid%20and%20Tree%20for%20Huge%20Data/Implement%20ListModel%20and%20TreeModel

link publish delete flag offensive edit

answered 2012-08-28 09:08:01 +0800

benbai gravatar image benbai
2228 6
http://www.zkoss.org

Hi Isaac,

If the item in selection is in the same page and it didn't work, you may need to implement the equals method properly, for example,

public class NameValuePair {
		...
	public boolean equals(Object obj) {
		if (obj != null
			&& obj instanceof NameValuePair
			&& isEqual(((NameValuePair)obj).getName(), getName())
			&& isEqual(((NameValuePair)obj).getValue(), getValue())) {
				return true;
			}
			return false;
	}
}

If the selection is not in the same page it might even not in the model, this is why the page will not be changed automatically. You can override the setSelection method to change page as needed, ex:

<zk>
	<zscript><![CDATA[
		import java.util.Comparator;
		import java.util.List;
		import java.util.ArrayList;
		import java.util.Set;
		import java.util.LinkedHashSet;
		import java.util.Date;
		import java.util.Collection;
		import java.util.Iterator;
		import org.zkoss.zul.AbstractListModel;
		import org.zkoss.zul.ext.Sortable;
		import org.zkoss.zul.Textbox;
		import org.zkoss.zul.Listbox;

		List fakeDB = new ArrayList();
		Textbox tbx;
		Listbox lbox;

		for (int i = 0; i < 10000; i++) {
			fakeDB.add("data " + i);
		}
		class FooListModel extends AbstractListModel implements Sortable {
		    private int _size = -1;
		    private Object[] _cache;
		    private int _beginOffset;
		    private static int fetchSize = 100;
		  
		    public int getSize() {
		        if (_size < 0)
		            _size = 10000;
		        return _size;
		    }
		    public Object getElementAt(int index) {
		        if (_cache == null || index < _beginOffset || index >= _beginOffset + _cache.length) {
		        	tbx.setValue(tbx.getValue() + "\nfetch data, time =  " + new Date());
		           loadToCache(index, fetchSize);
		        }
		        return _cache[index - _beginOffset];
		    }

		    public void sort(Comparator cmpr, boolean ascending) {
		        // do nothing
		    }

		    public String getSortDirection(Comparator cmpr) {
		        return "natural";   
		    }
		    // set selection and change page
		    public void setSelection(Collection selection) {
		    	super.setSelection(selection);
		    	Iterator it = selection.iterator();
		    	Object o;
		    	while (it.hasNext()) {
		    		o = it.next();
		    	}
		    	changePage(Integer.parseInt(((String)o).replace("data", "").trim()));
		    }
		    private void loadToCache(int index, int fetchSize) {
		    	_beginOffset = index - 30;
		    	if (_beginOffset < 0)
		    		_beginOffset = 0;
		    	if ((_beginOffset + fetchSize) > fakeDB.size())
		    		fetchSize = fakeDB.size() - _beginOffset;
 
		    	List dataList = new ArrayList();
		    	dataList.addAll(fakeDB.subList(_beginOffset, _beginOffset + fetchSize));
	    		_cache = dataList.toArray();
		    }
		}
		FooListModel model = new FooListModel();
		model.setMultiple(true);

		public void changePage (int index) {
			int pageSize = lbox.getPageSize();
			int page = index / pageSize;
			lbox.setActivePage(page);
		}
	]]></zscript>
	<button label="select item 1, 3">
    	<attribute name="onClick">
    		Set selection = new LinkedHashSet();
    		selection.add("data " + 1);
    		selection.add("data " + 3);
    		model.setSelection(selection);
    	</attribute>
    </button>
    <button label="select item 221, 223">
    	<attribute name="onClick">
    		Set selection = new LinkedHashSet();
    		selection.add("data " + 221);
    		selection.add("data " + 223);
    		model.setSelection(selection);
    	</attribute>
    </button>
    <textbox value="msg: " rows="3" width="300px">
    	<attribute name="onCreate">
    		tbx = self;
    	</attribute>
    </textbox>
    <listbox id="lb" model="${model}" mold="paging"
    	autopaging="true" pagingPosition="top">
    	<attribute name="onCreate">
    		lbox = self;
    	</attribute>
    </listbox>
</zk>

Regards,
Ben

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: 2012-08-06 22:54:50 +0800

Seen: 429 times

Last updated: Aug 28 '12

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