I want to implement a very common feature of Listbox with select mold, which I couldn't found on ZK.
Situation: The user selects the value from listbox. When the value is selected and the user open that listbox again, I need to change the model to the same model, but with empty listitem in front. If he selects that empty value, again the model has to be changed to the same, but without empty listitem at index 0.
I tried a lot of things like writing:
1) Dynamic model from ZUL. It worked, kind of, but I want to keep ZUL`s as simple and clean as possible.
<listbox id="x" mold="select" model="@load(not empty vm.criteria[self.id].selectedItem ?
vm.metaDataMap[self.id].model : vm.metaDataMap[self.id].modelWithEmptyValue)"
selectedItem="@bind(vm.criteria[self.id].selectedItem)">
<listitem>
<listcell label="@load(each.value)" value="@load(each)" />
</listitem>
</listbox>
2) Write SelectorComposer for my listbox. It did not worked properly, because the label and value sometimes disappears and it does not set the value to "@bind(vm.criteria[self.id].selectedItem)". And some problem with index`es
public class ListboxComposer extends SelectorComposer<Listbox> {
private static final long serialVersionUID = 1L;
public ListModelList<CaseStatusEnum> status = new ListModelList<CaseStatusEnum>(CaseStatusEnum.values());
public ListModelList<CaseStatusEnum> statusWithEmpty = new ListModelList<CaseStatusEnum>(CaseStatusEnum.values());
public Listbox comp;
public void doAfterCompose(Listbox comp) throws Exception {
super.doAfterCompose(comp);
comp.setModel(new ListModelList<CaseStatusEnum>(status));
statusWithEmpty.add(0, null);
}
public ListModelList<CaseStatusEnum> getStatus() {
return status;
}
@Listen("onSelect = listbox")
public void onSelect(SelectEvent<Listitem, CaseStatusEnum> evt) {
Listbox listbox = this.getSelf();
Listitem selectedItem = listbox.getSelectedItem();
int selectedIndex = selectedItem.getIndex();
if (listbox.getSelectedItem().getValue() != null) {
listbox.setModel(statusWithEmpty);
if (selectedIndex >= listbox.getModel().getSize()) {
listbox.setSelectedIndex(listbox.getModel().getSize()-1);
} else {
listbox.setSelectedIndex(selectedIndex+1);
listbox.getItemAtIndex(selectedIndex+1).setLabel(selectedItem.getLabel());
listbox.getItemAtIndex(selectedIndex+1).setValue(selectedItem.getValue());
}
} else {
listbox.setModel(status);
listbox.clearSelection();
}
}
}
and in my ZUL:
<listbox id="x" mold="select" apply="lt.pathxxx.ListboxComposer"
model="${composer.status}"
selectedItem="@bind(vm.criteria[self.id].selectedItem)">
<listitem>
<listcell label="@load(each.value)" value="@load(each)" />
</listitem>
</listbox>
3) I even tried to create custom component by extending listbox. But I didn`t make it too.
So basically, I want to write my own custom component by extending listbox, which could manipute the model according to whether there is selected item, or no(null)? What`s the proper way to do it?
EDIT: Basically, what I need is
<hlayout id="x">
<listbox mold="select" selectedItem="@bind(vm.criteria[self.parent.id].order)"
visible="@load(not empty vm.criteria[self.parent.id].order)">
<listitem label="" value="" />
<listitem label="Descending" value="desc" />
<listitem label="Ascending" value="asc" />
</listbox>
<listbox mold="select" selectedItem="@bind(vm.criteria[self.parent.id].order)"
visible="@load(empty vm.criteria[self.parent.id].order)">
<listitem label="Descending" value="desc" />
<listitem label="Ascending" value="asc" />
</listbox>
<hlayout>
I need all this in ONE listbox and the model(listitems) has to be set from java. Maybe I made it more clear now! Thanks for responses!
zul :
<listbox mold="select" model="@load(vm.listboxModel)" selectedItem="@bind(vm.selectedListBoxItem)" onSelect="@command('check')">
<listitem>
<listcell label="@load(each.value)" value="@load(each)" />
</listitem>
</listbox>
vm :
private ListModelList listData; // of course init and fill it
private Person selectedListBoxItem;
public ListModelList getListData() {
return listData;
}
public void setSelectedListBoxItem(Person selectedListBoxItem) {
this.selectedListBoxItem = selectedListBoxItem;
}
public Person getSelectedListBoxItem() {
return selectedListBoxItem;
}
@Command
@NotifyChange("listData")
public void check() {
if (selectedListBoxItem != null) {
if (listData.get(0) != null) {
System.out.println("added null");
listData.add(0, null);
}
} else {
if (listData.get(0) == null) {
System.out.println("removed null");
listData.remove(0);
}
}
}
edit: more like this? Did tested it (with the System.out.println("removed null");
so you can check that he does what he needs to do.
Hope this is what you wanted (Its what I understand of your question).
Greetz chill.