I have a
displaying a product catalog in Proudcts.xhtml
:
Agree with Matt. Change your behaviour to be Ajax bt adding and set to execute the @this and quantity and render the cart. That way it will only process that row, not the whole table.
Also I would change the action yo actionlistener.
Here,
<h:selectOneMenu value="#{ViewProductsManagedBean.quantityPurchased}">
You're basically binding the value of all input fields to one and same bean property. So, when the form gets submitted, every iteration of the table will override the bean property everytime with the submitted value of the current iteration round until you end up getting the value of the last row. If you have placed a debug breakpoint on the setter method, you should have noticed that.
This is definitely not right. You need to associate the input value with the currently iterated object. The simplest but naive way would be to directly associate it with the object:
<h:selectOneMenu value="#{product.quantityPurchased}">
This only tight-couples in your particular case the "quantity" model with the "product" model. It's functionally reasonable to keep them separated. A more proper solution is then to map the input value with currently iterated object as key (provided that the object has a proper equals()
and hashCode()
implementation, obviously):
<h:selectOneMenu value="#{ViewProductsManagedBean.quantitiesPurchased[product]}" converter="javax.faces.Integer">
With:
private Map<ProductEntity, Integer> quantitiesPurchased = new HashMap<>();
Regardless of the approach, in the action method, just iterate over it to collect them all.
Each line of your h:datatable
references the same variable ViewProductsManagedBean.quantityPurchased
. If the form is submitted, the value of ViewProductsManagedBean.quantityPurchased
will be set for each line again and again. That's why the value of the last row defines the final state of quantityPurchased
and this is the value you get in your method.