-
FEATURED COMPONENTS
First time here? Check out the FAQ!
I am really a fan of zk. But some of the concepts(?) still drive me crazy!
It took me now 2 hours to figure out that there is no easy way to use a combobox (in MVVM with model binding) and deal with the comboitem's "value" as the comobox' selected code instantly.
While this simple sample (works):
java:
public List<String> getList() {...} // "A", "B", "C"
public String getSelectedItem() {...}
public void setSelectedItem(String item) {...}
zul: <combobox model="@load(vm.list)" selectedItem="@bind(vm.selectedItem)" />
<template name="model">
<comboitem label="@load(each)" />
</template>
</combobox>
You cannot just add a "value" to the comboitem and expect this value to be returned when selected:
java:
public List<NameValuePair> getList() {...} // "A"->"1", "B"->"2", "C"->"3"
public String getSelectedItem() {...}
public void setSelectedItem(String item) {...}
zul: <combobox model="@load(vm.list)" selectedItem="@bind(vm.selectedItem)" />
<template name="model">
<comboitem label="@load(each.name)" value="@load(each.value)" />
</template>
</combobox>
Well, the setter setSelectedItem
gets called (!) but the value is NOT the value of the selected item (e.g. "2") BUT the mangeled instance name of the selected NameValuePair or Comboitem instance or ??? (huh??).
After googeling tons of questions and answers I now know that the selectedItem always deals with an instance of Comboitem and you have to use getValue() on this instance to get the real value. Same for setting the initial selection. Somehow same. Never as easy as a string compare!
And there are hundreds of other tips to get it done (custom item renderer, model class implementing Comparable, ...
Hey, isnt't it the most obvious use of a combobox to present a human readable label and let select a machine readable unique code and then use this code again to mark the selected item in the combobox?
I know that combobox obviously works as designed.
But then - sorry - the design is overengineered and crappy.
Still a fan ;-( Klaus
Thx, Senthil.
Your suggestion is what I mentioned as one of the hundreds of other tips to get it done. It works, but is not straight forward.
My personal favorite is what @gekkio posted in Combobox doesn't have key-value pairs working like html <SELECT>
tag - Please Help..
The "Scala" implementation of a custom combobox class (extending combobox) introducing a "selectedValue" attribute is exatcly what I am missing from the standard implementation!
I understand, that the "value" attribute of the standard combobox cannot serve this need as it should reflect the "textbox" content of the (non-readable-) combobox. So adding an intuitive new attribute selectedValue (next to selectedIndex and selectedItem) is a brillant idea.
I translated gekkio's "Scala" proposal into Java like this:
package test;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.SelectEvent;
import org.zkoss.zul.Combobox;
import org.zkoss.zul.Comboitem;
public class CustomCombobox extends Combobox {
private static final long serialVersionUID = 1L;
private String _selectedValue = null;
public String getSelectedValue() {
return _selectedValue;
}
public void setSelectedValue(String selectedValue) {
_selectedValue = selectedValue;
}
public void onAfterRender() {
setReadonly(true);
int selectedIndex = 0;
for (Comboitem item : getItems()) {
if (null != _selectedValue && _selectedValue.equals(item.getValue())) {
setSelectedIndex(selectedIndex);
break;
}
selectedIndex++;
}
}
public void onSelect(SelectEvent<Comboitem, Event> event) {
Comboitem selectedItem = event.getReference();
if (selectedItem != null) {
setSelectedValue((String) selectedItem.getValue());
}
}
}
As gekkio did not regard the MVVM binding there was a need to change the initial event handler from "onCreate" to "onAfter Render". And in order to allow two-way data binding (@load and @save) an extension to the standard component's language-addon is neccessary in you e.g. WEB-INF/zk/lang-addon.xml like:
...
<component>
<component-name>combobox</component-name>
<extends>combobox</extends>
<annotation>
<annotation-name>ZKBIND</annotation-name>
<property-name>selectedValue</property-name>
<attribute>
<attribute-name>LOAD_EVENT</attribute-name>
<attribute-value>onAfterRender</attribute-value>
</attribute>
<attribute>
<attribute-name>SAVE_EVENT</attribute-name>
<attribute-value>onChange</attribute-value>
</attribute>
<attribute>
<attribute-name>ACCESS</attribute-name>
<attribute-value>both</attribute-value>
</attribute>
</annotation>
</component>
...
Then you can use the customCombobox in a zul:
<combobox model="@load(vm.nameValuePair)"
readonly="true"
use="test.CustomCombobox"
selectedValue="@bind(vm.value)">
<template name="model" var="entry">
<comboitem
label="@load(entry.key)"
value="@load(entry.value)" />
</template>
</combobox>
The "use=" tag is one option. One can also shift the extension of combobox entirely into the language-addon.
This solution (which I heavily wish to be implemented in the standard combobox) works quite fine with one important bug which I describe in the next posting.
The above solution (which I heavily wish to be implemented in the standard combobox) works quite fine with one important bug:
the evaluation of selectedValue for @save (or @bind) is always one UI cycle too late ????.
If I select another entry in the combobox the setter in the view model always gets the previous value over and over. It seems as if the new selected value is set after the view model is satisfied.
PLEASE ASSIST!!!
Asked: 2016-01-02 22:21:56 +0800
Seen: 93 times
Last updated: Jan 04 '16
wrong valueException come in front of modal popup [closed]
Use parameters in a conditional @command
Problems with multiple press and onCtrlKey
MVVM @save on the fly [closed]
Unable to activate destroyed desktop
org.zkoss.zk.ui.UiException: java.lang.ClassNotFoundException
How to put a image or Letter over image on a specific XY Coordinate