I have a datatable with 10 rows. The first column in each row has a valuechange event. For e.g it's like, we enter the accountnumber and the valuechangeevent retrieves the account information.
Now, i also have another column to display the cost. If user enters some amount, it should add up all the amounts in all the rows and display it on a different column.
But the problem is, the user can enter a second account number at any point of time. then it will again be a valuechange event. now, since it is a value change event, the information in the first row is not updated in the DataModel. As such, i am losing the previously entered amount for the first row.
Is there a way to implement this functionality without losing the previous information?
Until just recently, I would have said that there is no way to do what you want. After a lot of research on the JSF lifecycle phases, I believe there is a way to get this to work within JSF, without having to go to an Ajax-like approach.
The essence of the problem is the rigid order of lifecycle phases in JSF. Updates to the data model (the backing bean) don't occur until after the request parameters have been parsed and standard validation rules applied. Value Change Events, which can only be fired from certain input components such as HtmlInputText, HtmlSelectOneRadio etc, occur from a component with the immediate="true" attribute set. When this happens, a specified ValueChangeListener will be called at the "Apply Request Values" phase, which will happen before the model data is updated. If you want to skip validation and updating of model data, you have to call renderResponse( ) on the FacesContext, and that will skip those phases...if you don't, it will proceed through validation and model data update normally.
Here is an example of a properly formatted JSF component that will do as I described:
What does the onchange="submit( )" do? It causes the form to be submitted to the URL specified in the form tag...in the case of JSF, all pages submit back to themselves, and are trapped by the FacesServlet. At this point the JSF lifecycle takes over, which includes the following phases: 1. Restore View 2. Apply Request Values 3. Process Validations 4. Update Model Values 5. Invoke Application 6. Render Response
So far, so good...the problem occurs when a component (specified with an immediate="true" attribute) needs to update another component, such as a text box. For this to work, both components have to have the immediate="true" attribute set. If you do this, you will be able to set the value in the second component directly in the ValueChangeListener method, in a manner something like this:
I think this will get you through the problem you are describing. If it doesn't, there is another approach that requires you to manipulate the event queue directly, and you really shouldn't go there unless absolutely necessary.
Just registered and logged in to thanks for the useful advice by Tom Fulton. I was facing this problem:
I need to capture a string in an InputText component, and everytime I press Enter, the value should be processed, a search done in a database and some data updated in a datatable component. But, the text field should get ready for a new input, since the data already in the datatable may be related to the new input. This readiness should be done by clearing the InputText. Using the ViewRoot and immediate components as you say, have solved my problem...