< h:dataTable>中的输入字段总是收到列表中最后一个项目的值 [英] Input field in <h:dataTable> always receives value of last item in list

查看:96
本文介绍了< h:dataTable>中的输入字段总是收到列表中最后一个项目的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个< h:dataTable> Proudcts.xhtml 中显示产品目录:

 < h:form name =ViewProductsManagedBean> 
< h:dataTable var =productvalue =#{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 =1itemLabel =1/>
< f:selectItem itemValue =2itemLabel =2/>
< f:selectItem itemValue =3itemLabel =3/>
< f:selectItem itemValue =4itemLabel =4/>
< f:selectItem itemValue =5itemLabel =5/>
< / h:selectOneMenu>
< / h:column>
< h:column>
< h:commandButton action =#{ViewProductsManagedBean.addItemToCart(product)}value =添加到购物篮/>
< / 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 quantity购买;
private String result;

@EJB
ProductLocal productFacadeBean;

@EJB
CartFacade购物车功能;

私人列表< ProductEntity> productsList = new ArrayList<>();
私人列表< StockEntity> stocksList = new ArrayList();
private ProductEntity产品;

@PostConstruct
private void init(){
setProductsList();
product = new ProductEntity();
}

public void addItemToCart(ProductEntity product){
int quantity = this.quantityPurchased;
cartFunctions.addItemToCart(产品,数量);
System.out.println(product.toString());
}

// getters + setters
}

问题出在< h:selectOneMenu> 以选择数量。无论选择什么值,受管Bean总是在数量上接收值为1的值,在产品目录的最后一项中更改数量时为EXCEPT,在这种情况下,所有项目的数量将更改为为目录中的最后一个项目,并将正确的数量发送到受管Bean。



这是怎么引起的,如何解决?

解决方案

这里,

 < h:selectOneMenu value =#{ViewProductsManagedBean.quantityPurchased}> 

您基本上将所有输入字段的值绑定到一个和同样的bean属性。所以,当表单被提交时,表的每次迭代都会使用当前迭代循环的提交值来重载bean属性,直到最终得到最后一行的值为止。如果您已经在setter方法上放置了一个调试断点,那么您应该注意到。



这绝对不对。您需要将输入值与当前迭代对象相关联。最简单但天真的方法是将其直接与对象相关联:

 < h:selectOneMenu value =#{product .quantityPurchased}> 

只有在特定情况下,数量模型与产品模型紧密相连。将它们分开是功能上合理的。然后一个更合适的解决方案是将输入值与当前迭代对象映射为关键字(只要对象具有正确的 equals() hashCode )实现,显然):

 < h:selectOneMenu value =#{ViewProductsManagedBean.quantities [product]}converter =javax.faces.Integer> 

With:

 code> private Map< ProductEntity,Integer> quantityPurchased = new HashMap<(); 

无论采取什么方法,在action方法中,只需要迭代就可以收集所有这些。 p>

I have a <h:dataTable> displaying a product catalog in 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>

With this managed 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
}

The problem is with the <h:selectOneMenu> to select the quantity. No matter what value is selected, the managed bean always receives a value of 1 for quantity, EXCEPT when the quantity is changed in the last item of the product catalog, in which case the quantity for ALL the items change to the value selected for the last item in the catalog, and the correct quantity is sent to the managed bean.

How is this caused and how can I solve it?

解决方案

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.

这篇关于&lt; h:dataTable&gt;中的输入字段总是收到列表中最后一个项目的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆