-
FEATURED COMPONENTS
First time here? Check out the FAQ!
Hi to everybody.
As shown in zk demo, it's easy to obtain a combobox with auto-complete function.
Is it possible to have auto-complete comboboxes with databinding?
Something like:
<combobox model="${weeklyModel}" selectedItem="@{selected.timeRange.end}" value="@{selected.timeRange.end, converter='PartialTypeConverter'}" readonly="true"> <comboitem self="@{each=endd}" label="@{endd, converter='PartialTypeConverter'}" value="@{endd}"/> </combobox>
Hi SerFingolfin,
No support yet,
The auto complete has to implement the ListSubModel interface,
and the data binding has to implement the BindingListModel interface,
You can post a feature request here.
Hello, I'm new to ZK and I'm loving it so far. I'd like to know if I can use the autocomplete function with a list of beans e.g. Product and select some specific value like the ID and display the Description on the label. I've found a lot of examples, but they are made with strings or numbers or databinding, and I only need an autocomplete combobox to display desc and save its corresponding id. I'm sorry if I'm posting this in the wrong place.
Hi arscek,
I have created a sample,
package j25jldcg$v1;public class MyItem {
private int id;
private String name;public MyItem(int id, String name) {
super();
this.id = id;
this.name = name;
}public String getName() {
return name;
}public int getId() {
return id;
}
public String toString() {
return id+": "+name;
}}
package j25jldcg$v1;import org.zkoss.zk.ui.*;
import org.zkoss.zk.ui.event.*;
import org.zkoss.zk.ui.util.*;
import org.zkoss.zk.ui.ext.*;
import org.zkoss.zk.au.*;
import org.zkoss.zk.au.out.*;
import org.zkoss.zul.*;
import java.util.*;public class TestComposer extends GenericForwardComposer{
private Label msg;
private Combobox cb;
public void doBeforeComposeChildren(Component comp) throws Exception {
super.doBeforeComposeChildren(comp);
String[] _dict = {
"abacus", "accuracy", "acuity", "adage", "afar", "after", "apple",
"bible", "bird", "bingle", "blog",
"cabane", "cape", "cease", "cedar",
"dacron", "defacto", "definable", "deluxe",
"each", "eager", "effect", "efficacy",
"far", "far from",
"girl", "gigantean", "giant",
"home", "honest", "huge",
"information", "inner",
"jump", "jungle", "jungle fever",
"kaka", "kale", "kame",
"lamella", "lane", "lemma",
"master", "maxima", "music",
"nerve", "new", "number",
"omega", "opera",
"pea", "peace", "peaceful",
"rock", "RIA",
"sound", "spread", "student", "super",
"tea", "teacher",
"unit", "universe",
"vector", "victory",
"wake", "wee", "weak", "web2.0",
"xeme",
"yea", "yellow",
"zebra", "zk",
};
List list = new ArrayList();
for (int i = 0; i < _dict.length; i++)
list.add(new MyItem(i, _dict[i]));
comp.setAttribute("dictModel", new SimpleListModel(list) {
protected boolean inSubModel(Object key, Object value) {
String idx = key.toString();
MyItem myItem = (MyItem)value;
return idx.length() > 0 && myItem.getName().startsWith(idx);
}
});
comp.setAttribute("renderer",new ComboitemRenderer () {
public void render(Comboitem item, Object data) throws Exception {
MyItem myItem = (MyItem)data;
item.setLabel(myItem.getName());
item.setValue(myItem);
}
});
}
public void onSelect$cb() {
msg.setValue(cb.getSelectedItem().getValue().toString());
}
}
<zk>
<window border="normal" title="Auto-complete" apply="j25jldcg$v1.TestComposer">
<combobox model="${dictModel}" itemRenderer="${renderer}" id="cb" autodrop="true"/>
<label id="msg"/>
</window>
</zk>
Hi jimmyshiau
Can you please give me MVVM Version of the above example code ?
Regards Senthil
Any help please
Any help please.....................
To use ListSubModel with Java Beans, you need to provide appropriate Comparator.
simple sample:
test.zul
<zk>
<div apply="org.zkoss.bind.BindComposer"
viewModel="@id('vm') @init('test.TestVM')">
<combobox model="@load(vm.model)" autodrop="true"
autocomplete="true">
<template name="model">
<comboitem label="@load(each.label)" description="@load(each.desc)" />
</template>
</combobox>
</div>
</zk>
TestVM.java
package test;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import org.zkoss.zul.ListModel;
import org.zkoss.zul.ListModelList;
import org.zkoss.zul.ListModels;
/**
* tested with ZK 6.5.2
*
* @author benbai
*
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public class TestVM {
ListModelList _model;
public ListModel getModel () {
if (_model == null) {
List l = new ArrayList();
l.add(new Data("Item 1", "Desc 1"));
l.add(new Data("Item 2", "Desc 2"));
l.add(new Data("Object 1", "ObjDesc 1"));
l.add(new Data("Object 2", "ObjDesc 2"));
_model = new ListModelList(l);
}
return ListModels.toListSubModel(_model, getComparator(), 25);
}
private Comparator getComparator () {
return new Comparator () {
public int compare (Object o1, Object o2) {
if (o1 == null) return -1;
Data d2 = (Data)o2;
if (o1 instanceof String) {
String s1 = (String)o1;
if (s1 == null || s1.isEmpty())
return -1;
return d2.getLabel().startsWith(s1)?
0 : s1.compareTo(d2.getLabel());
} else if (o1 instanceof Data) {
Data d1 = (Data)o1;
return d1.getLabel().compareTo(d2.getLabel());
}
return -1;
}
};
}
public static class Data {
String _label;
String _desc;
public Data (String label, String desc) {
_label = label;
_desc = desc;
}
public String getLabel () {
return _label;
}
public String getDesc () {
return _desc;
}
}
}
Thank you benbai. Can i use this for the table which contains more than 30,000 records ?.
Or do you have any other suggestion ?
For 30000 records is okay I think, you can also try implement ListSubModel by your self to get live data from DB directly instead of put all data in memory (trade off: probably increase the processing time). Or you can try keep a static list as the data provider and fetch data from it dynamically.
e.g., the updated TestVM.java, keep only selection in memory
package test;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.zkoss.zul.ListModel;
import org.zkoss.zul.ListModelList;
import org.zkoss.zul.ListSubModel;
import org.zkoss.zul.event.ListDataListener;
import org.zkoss.zul.ext.Selectable;
/**
* tested with ZK 6.5.2
*
* @author benbai
*
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public class TestVM {
public ListModel getModel () {
return new CustomSubModel(false);
}
public static class CustomSubModel<E> implements ListModel<E>, ListSubModel<E>,
Selectable<E>, java.io.Serializable {
private boolean _multiple;
private Set _selection = new HashSet();
private ListModelList<E> _model = new ListModelList(new ArrayList(), true);;
public CustomSubModel (boolean multiple) {
_multiple = multiple;
}
public ListModel getSubModel(java.lang.Object value, int nRows) {
Set oldSelection = null;
Set newSelection = new HashSet();
List datas = new ArrayList();
if (value != null && !value.toString().isEmpty()) {
// dynamically create data
// assume fetch data from DB here
for (int i = 0; i < 5; i++) {
datas.add(new Data(value.toString() + "__" + i, value.toString() + "Desc__" + i));
}
}
if (_model != null) {
// join current selection
oldSelection = _model.getSelection();
_selection.addAll(oldSelection);
}
for (Object o : _selection) {
Data d = (Data)o;
if (datas.contains(o)) {
newSelection.add(o);
}
}
final Selectable model = new ListModelList(datas, true);
model.setMultiple(_multiple);
model.setSelection(newSelection);
_model = (ListModelList)model;
return (ListModel)model;
}
public E getElementAt(int index) {
return _model.getElementAt(index);
}
public int getSize() {
return _model.getSize();
}
public void addListDataListener(ListDataListener l) {
_model.addListDataListener(l);
}
public void removeListDataListener(ListDataListener l) {
_model.removeListDataListener(l);
}
@SuppressWarnings("unchecked")
private Selectable<E> getSelectModel() {
return (Selectable<E>) _model;
}
public Set<E> getSelection() {
return getSelectModel().getSelection();
}
public void setSelection(Collection<? extends E> selection) {
getSelectModel().setSelection(selection);
}
public boolean isSelected(Object obj) {
return getSelectModel().isSelected(obj);
}
public boolean isSelectionEmpty() {
return getSelectModel().isSelectionEmpty();
}
public boolean addToSelection(E obj) {
return getSelectModel().addToSelection(obj);
}
public boolean removeFromSelection(Object obj) {
return getSelectModel().removeFromSelection(obj);
}
public void clearSelection() {
getSelectModel().clearSelection();
}
public void setMultiple(boolean multiple) {
getSelectModel().setMultiple(multiple);
}
public boolean isMultiple() {
return getSelectModel().isMultiple();
}
}
public static class Data {
String _label;
String _desc;
public Data (String label, String desc) {
_label = label;
_desc = desc;
}
public String getLabel () {
return _label;
}
public String getDesc () {
return _desc;
}
public boolean equals (Object o) {
if (o != null && (o instanceof Data)) {
Data d = (Data)o;
return d.getLabel().equals(_label)
&& d.getDesc().equals(_desc);
}
return false;
}
}
}
For more information, please refer to the code:
Again thanks benbai. The first options seems to be ok in my project. But how we can validate if the user enter the value if that is not in the list ?
Can we have selecteditem property, and in that case, it will be null ? Please let me know.
Asked: 2011-02-09 03:04:18 +0800
Seen: 1,245 times
Last updated: Jul 08 '13
search button using validation
my login/index zul page is loading twice, where as i am only calling it once
Multiple selection using ListModelMap<Key, Obj>
Notify Form of property change
How to handle lists and complex types with form?
multiple checkboxes in a row of listbox
How to bind a Model with a Viewmodel