Combobox not binding when cleared

dastultz
797 8

Hi, I'm using FL 8/29. I have a Richlet that binds a Combobox (with items that have value rather than a model) to a bean. When I type and autocomplete (and hit tab) or select an item from the dropdown, the value is immediately copied to the bean. But if I then select the text and delete it, then hit tab, the value (null?) is not written to the bean. A subsequent call to binder.saveAll() will do it, but I'm wondering if this is a bug.

I'm sure you would like an example but I don't know ZUL very well. Here's a start, but I can't even get this to work. Maybe someone can help me get this working as a basic bind and then we'll see if it behaves the same way my richlet does. It should be obvious, but I'm trying to bind an integer to the selected item:

<zk>
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>

<window>
<zscript>
class Thing {
private int val = 2;

public int getVal() { System.out.println("getVal() " + this.val); return val; }
public void setVal(int val) { System.out.println("setVal() " + val); this.val = val; }
}
Thing thing = new Thing();
</zscript>
<combobox id="cmb" constraint="strict" selectedItem="@{thing.val}">
<comboitem value="1" label="One"/>
<comboitem value="2" label="Two"/>
<comboitem value="3" label="Three"/>
</combobox>

</window>
</zk>

Thanks.

/Daryl

delete retag edit

10 Replies

robertpic71
1275 1

Hi Daryl

I simplified the code (selectItem has to be same instance as value, in this case String):

<zk>
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" ?>
<window>
<zscript>String val = "0";</zscript>
<combobox id="cmb" constraint="strict" selectedItem="@{val}">
<comboitem value="1" label="One" />
<comboitem value="2" label="Two" />
<comboitem value="3" label="Three" />
</combobox>
Selected:
<label id="outval" value="@{val}" />
</window>
</zk>

In my opinion this is a bug. I am not sure about the databinder, but maybe the coreproblem is, that there is no onSelect-Event when the user deletes the combobox.

/Robert

dastultz
797 8

Thanks, Robert, while I wasn't having any problem in my richlet with int <--> String, this does illustrate the problem, I think. It would be great if the Zk experts could look at this.

Robert, this condition stems from my constraint work we've been discussing. Let's say I have only "strict" and not "no empty" on my combobox. When I click save, I need to check for null. Like you, I prefer to use the bean rather than the control:

checkValues();
saveBean();

Since the combobox is not necessarily saved to the bean due to this apparent bug, I do this:

binder.saveAll()
checkValues();
saveBean();

This gets my values to the bean, but subsequent WrongValueException thrown from checkValues() fails to post the error message box (my thread is interrupted but I get no visual feedback). If I do it the first way, but use the component instead of the bean it works ok. Unfortunately I can't seem to reproduce this in ZUL. Anybody else seen such a thing?

Looking at the source code for InputElement we see:

protected void checkUserError() throws WrongValueException {
if (_errmsg != null)
throw showCustomError(new WrongValueException(this, _errmsg));
//Note: we still throw exception to abort the exec flow
//It's client's job NOT to show the error box!
//(client checks z.srvald to decide whether to open error box)

if (!_valided && _constr != null)
setText(coerceToString(_value));
}

Could this have anything to do with it? How does the client decide whether or not to open the error box?

/Daryl

dastultz
797 8

Interestingly, if I do this instead it works:

binder.saveComponent(myCombobox);
checkValues();
saveBean();

binder.saveAll calls init before iterating over components. What's going on there that could cause of this problem?

/Daryl

dastultz
797 8

My mistake: binder.saveComponent also calls init. I happen to have two combo boxes on the page. If I call save component for both the message box does not show, but if I call save component for just one the message shows. I don't get it.

/Daryl

dastultz
797 8

Well, I've got a workaround by binding combobox with onBlur as well as onSelect. Maybe onBlur is sufficient. Any input?

/Daryl

robertpic71
1275 1

>> Maybe onBlur is sufficient.
It should be, i found only one case (keyboard action on this field, i.e. enter).

>> Well, I've got a workaround by binding combobox with onBlur as well as onSelect
I've tested with onChange and it seems that handels all occurrences. Maybe the default save-event for comboboxes should be onChange instead of onSelect.

/Robert

dastultz
797 8

Thanks for testing this, Robert. I'm using onChange now and it works fine except for one thing. Suppose I select a value from the list and populate all the other fields properly. My bean now has all good values. If I then type in a bogus value and hit "save" I briefly see an error message from the "strict" constraint, then the save succeeds using the original good value! It seems when using strict, the binding save event (from onChange) is interrupted. If I remove the strict constraint it works fine since I'm testing values in the bean before saving.

/Daryl

robertpic71
1275 1

Thanks for your testing, Daryl. There seems no "one event to catch all occurrences". I think, i will do a binder.saveXX in my save/submit method and maybe i remove some default-events.

BTW: To avoid binder.saveAll() (i.e. because there are many fields in different forms) you could group your components for databinding.
In this Example i group my inputfields in the grid id="input".

binder.save(input); // input = Grid

save also all childs from input.

Maybe you know that already or maybe it helps.

@ZK Team
In my opinion the defaultevents for Combobox.selectedItem databinding should handle all occurrences. Should i post a bug?

dastultz
797 8

>>BTW: To avoid binder.saveAll() (i.e. because there are many fields in different forms) you could group your components for databinding.

Since I am in "richlet land" I don't have an equivalent of
<?init class="org.zkoss.zkplus.databind.AnnotateDataBinderInit" arg0="simpleWindow"?>
which would get me one binder for the whole page. Sure, I could make one, but my current UI pattern involves lots of "list" tables and "property tables", the latter being a form to edit the properties of an entity. Each list and property table has its own binder.

I finally commented out binder.saveAll() in my property table since I managed to get all properties saving to the bean onChange/onSelect, etc., so I just call bean.save().

>In my opinion the defaultevents for Combobox.selectedItem databinding should handle all occurrences. Should i post a bug?

I happen to be using Combobox as a handy substitute for Listbox(select) to allow typing partial text to select an item. It's also a textbox and other applications may only be concerned with the textual content rather than selected items. So while it doesn't work out of the box the way I would like, it doesn't seem like a bug. Oh wait, you are saying that if the binding specifies the selectedItem attribute, it should set null for when the text doesn't match a selection? Yeah, that I agree with.

/Daryl

henrichen
3869 2

Robert,

It was a specification decision. That is, if we support "unselect" in combobox. In listbox, end user got no chance to do such things. Then can we do it in combobox? I think we can post a feature request first; then we discuss this from there. Thanks.

[hide preview]