<h:datatable>中的输入字段始终接收列表</h:datatable>中最后一项的值

时间:2015-01-23 06:48:38

标签: jsf jsf-2 datatable

我有<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。

这是如何引起的?如何解决?

3 个答案:

答案 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和数量并呈现购物车。这样它只会处理该行,而不是整个表。

另外我会改变动作你的动作玩家。