I have an address form, where user changes postal code, it call valuechangelistener to bring back city and updates on the screen. It works fine when user change postal code, then clicks somewhere else on the form.
The problem is that when user change postal code and then clicks save right away. The city is then updated (for 1 sec) on the screen... and then it's switched back to the old value (and obviously saved with the old city).
I want to valuechangelistener to update the city when user is submitting the form as well... how can this be done? Any help highly appreciated.
You should not attempt to use a valueChangeListener to update backing bean data. AFTER the valueChangeListeners are called, a later phase in the JSF lifecycle updates the bean properties automatically, and will therefore ovrlay whatever you did in the listeners. Plus, the listener will not fire at all unless the incoming value for that listener is different from the value that is already in the backing bean.
Also "immediate" doesn't mean "do it now", it means "do it without validating/updating data". It actually shouldn't even be a valid option on an inputText control unless IceFaces is doing something I don't know about.
An IDE is no substitute for an Intelligent Developer.
Joined: Apr 13, 2012
ValueChangeListener is called when a postal code is changed and user clicks somewhere else on the screen to bring back the address.... which is what my requirement is and it's correct.
however, it is also called when user clicks on "save"... it's called first, the the bean is overriden with whatever is on the screen.
I'm thinking of two solutions unless someone can help with another
1) Is it possible to check in the ValueChangeListener that if action was "save" then skip the content of the method and do not update the values
2) Or, can I check what the current value on the screen is from the ValueChangeListener?
JSF is based on HTTP, HTTP is a batch-mode protocol. It operates on the basis of submitted forms, unlike more interactive client/server systems where events travel to and from the server at the keystroke or field level. The "partialSubmit" attribute on your inputText control limits what fields on the form are submitted - otherwise all fields would be submitted when the associates action fired. The Save button has no such constraint, so all fields ARE submitted.
When a form (or partial form) is submitted to the server, the first thing that JSF does is validate all of the submitted control values. If even ONE of them fails validation, the processing is short-circuited and a response is sent back to the client with errors.
If you have converters, JSF will then convert the incoming values as needed. If a validator throws an exception, see above.
If validation AND conversion succeed, the incoming values are compared against the current property values of the backing bean(s). For properties whose present values differ from the incoming values, the associated valueChangeListener(s) are fired, passing in the new and old values plus the UIComponent of the associated control. No warrantees express or implied on what happens if you attempt to modify other values being listened to while in a listener and what works today may fail tomorrow.
Once all the the above has occurred, the backing bean(s) have their properties automatically updated. JSF takes the incoming data values and invokes the propery "set" methods to inject the updated values into the bean(s).
The bean has now been updated with guaranteed valid property values. Assuming you don't meddle with the process, it can be safely assumed that ALL backing bean property values are valid as defined by the constraints of the input controls, their validators and their converters.
Having done that, the source of the submit operation is examined and if there are actionListeners attached to it, those listeners are then fired. Finally, a check is made to see if there is an associated POJO action method and if so, that action method is invoked.
A partial submit can get away with invalid form values because only the submitted controls are passed through the JSF lifecycle. A full submit ("Save button") requires that ALL form controls have valid values, as explained above.
Joined: Apr 13, 2012
Thank you for for such a good and through explanation. I sort had an idea of the lifecycle but you made it pretty clear now.
However, I still don't know how to solve my problem. Any sugeestions on how to handle it?
If you get rid of all the Listeners and bindings, phase listeners &Co., you'll do better. The more JSF-specific you make your design, the more trouble it will cause you. Probably 95% of what people need to do in JSF can be done with simple POJO code. I think your #1 problem was in attempting to set a property value in a listener, only to have JSF stomp on it when it does its automatic updates.
If you want to pre-set the City name via AJAX when a postal code is selected, attach an action method to the postal code control. This action method would then examine the current value of the backing bean's postal code (which would have been updated automatically) and set the backing bean's city accordingly. You probably need an IceFaces directive to cause the UI value of City to be updated to reflect that change, but I'm not familiar with IceFaces AJAX. The RichFaces version would be to add "reRender="city"" to the postal code's AJAX properties. No JSF-specific code required to do any of this. In fact, not only is this done in POJO code, it's not even very complicated POJO code!
As a general rule, I recommend keeping the actual EL code as simple as possible - if only because it's such a pain to debug, but also because excessively-complex EL is often a sign that the MVC separation of concerns contract is being violated. My own personal preferences run to something more like this:
That collapses the VDL to the following (having also removed the listeners and other questionable stuff).