# How to change page on listbox after changing selection?

iwagner
45

In my zul file I have something like this:

<listbox id="mylist" autopaging="true" mold="paging">
<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>();
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 retag edit

## 11 Replies

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.

iwagner
45

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

iwagner
45

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

sjoshi
3493 1 8
http://zkframeworkhint.bl...

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

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

Hi Isaac,

<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();

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 answered 2012-08-20 14:50:22 +0800 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. answered 2012-08-20 17:46:19 +0800 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. answered 2012-08-21 06:32:44 +0800 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 answered 2012-08-27 19:58:33 +0800 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 answered 2012-08-28 09:08:01 +0800 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

[hide preview]