我有<h:dataTable>
在Proudcts.xhtml
显示产品目录:
<h:form name="ViewProductsManagedBean">
<h:dataTable var="product" value="#{ViewProductsManagedBean.productsList}">
<h:column>
<h:outputText value="#{product.productid}" />
</h:column>
<h:column>
<h:outputText value="#{product.itemcode}" />
</h:column>
<h:column>
<h:outputText value="#{product.itemdescription}" />
</h:column>
<h:column>
<h:outputText value="#{product.unitprice}" />
</h:column>
<h:column>
<h:selectOneMenu value="#{ViewProductsManagedBean.quantityPurchased}" required="true">
<f:selectItem itemValue="1" itemLabel="1" />
<f:selectItem itemValue="2" itemLabel="2" />
<f:selectItem itemValue="3" itemLabel="3" />
<f:selectItem itemValue="4" itemLabel="4" />
<f:selectItem itemValue="5" itemLabel="5"/>
</h:selectOneMenu>
</h:column>
<h:column>
<h:commandButton action="#{ViewProductsManagedBean.addItemToCart(product)}" value="Add to basket" />
</h:column>
</h:dataTable>
</h:form>
使用此托管bean:
@ManagedBean(name="ViewProductsManagedBean")
@SessionScoped
public class ViewProductsManagedBean {
private double unitprice;
private String itemdescription;
private String itemcode;
private int quantityPurchased;
private String result;
@EJB
ProductLocal productFacadeBean;
@EJB
CartFacade cartFunctions;
private List<ProductEntity> productsList = new ArrayList<>();
private List<StockEntity> stocksList = new ArrayList<>();
private ProductEntity product;
@PostConstruct
private void init(){
setProductsList();
product = new ProductEntity();
}
public void addItemToCart(ProductEntity product) {
int quantity=this.quantityPurchased;
cartFunctions.addItemToCart(product, quantity);
System.out.println(product.toString());
}
// getters+setters
}
问题在于<h:selectOneMenu>
选择数量。无论选择什么值,托管bean总是在数量上接收值1,在产品目录的最后一项中更改数量时除外,在这种情况下,所有项目的数量将更改为为目录中的最后一项,并将正确的数量发送到托管bean。
这是如何引起的?如何解决?
答案 0 :(得分:3)
下面,
<h:selectOneMenu value="#{ViewProductsManagedBean.quantityPurchased}">
您基本上将所有输入字段的值绑定到同一个bean属性。因此,当表单被提交时,表的每次迭代都将使用当前迭代轮次的提交值覆盖bean属性,直到您最终获得最后一行的值。如果你在setter方法上放置了一个调试断点,你应该注意到了。
这绝对不对。您需要将输入值与当前迭代的对象相关联。最简单但最天真的方式是直接将其与对象相关联:
<h:selectOneMenu value="#{product.quantityPurchased}">
在你的特定情况下,这只是紧密耦合的数量&#34;模型与&#34;产品&#34;模型。保持它们分离在功能上是合理的。然后,更合适的解决方案是将输入值与当前迭代的对象映射为键(假设该对象具有正确的equals()
和hashCode()
实现,显然):
<h:selectOneMenu value="#{ViewProductsManagedBean.quantitiesPurchased[product]}" converter="javax.faces.Integer">
使用:
private Map<ProductEntity, Integer> quantitiesPurchased = new HashMap<>();
无论采用何种方法,在动作方法中,只需迭代它就可以全部收集它们。
答案 1 :(得分:1)
h:datatable
的每一行都引用相同的变量ViewProductsManagedBean.quantityPurchased
。如果提交了表单,则会一次又一次为每一行设置ViewProductsManagedBean.quantityPurchased
的值。这就是为什么最后一行的值定义了quantityPurchased
的最终状态,这是你在方法中得到的值。
答案 2 :(得分:-1)
同意马特。将您的行为更改为Ajax bt添加并设置为执行@this和数量并呈现购物车。这样它只会处理该行,而不是整个表。
另外我会改变动作你的动作玩家。