JSF & ui:repeat - 将对象添加到购物车时出现问题



我再次需要一些帮助来完成我用Java Server Faces编写的披萨搜索程序。

程序:用户可以通过输入表单来搜索披萨。过滤搜索是可能的,因为用户可以决定是否搜索披萨名称、披萨id或其他指定条件。该程序将生成一个SQL查询,返回pizza对象并将其存储到对象列表中。JSF页面显示pizza对象的列表,方法是通过一个ui:repeat标签对它们进行迭代。显示披萨名称、披萨ID、可用尺寸(显示为单选按钮(和可能数量的列表。对于每个显示的披萨对象,都有一个"添加到购物车按钮",用于将披萨添加到所选尺寸和数量的参数化值下的购物车中。

问题:几乎所有内容都显示正确。但是,当要将披萨添加到购物车时,会出现错误。如果用户搜索特定的披萨,那么通过将披萨ID、所选尺寸和所选数量提交到添加到购物车的方法将不会出现问题。但是,当列表包含不止一个披萨对象时,通过提交正确的披萨ID值、选择的尺寸和选择的数量,只有最后一个披萨才能正确添加到购物车中。如果用户试图将上面的一个披萨放进他的购物车,那么将采用之前提交的所选尺寸和数量,前提是之前已经成功执行了"添加到购物车操作"。如果不是,无论用户选择什么尺寸和数量,都将提交0。

示例:用户搜索"披萨萨拉米"。他在手推车上加了两个40码的。(选择披萨ID:1;选择尺寸:40;选择数量2(。一切都执行正确。但在那之后,用户会搜索所有的披萨。他想添加显示列表中的第一个比萨饼。这个披萨只有30码。他选择了3个30码的披萨,然后点击"添加到购物车按钮"。程序采用chosenSize和chosenQuantity的先前参数(chosenSize:40;chosenQuantity:2(。

PizzaSearch的代码片段:

@ManagedBean
@SessionScoped
public class PizzaSearch {
   // variables in order to submit the search criteria
   private List<PizzaObject> results = new ArrayList<PizzaObject>();
   // methods to generate the search
   // each search result will fill/replace the list of pizza objects 'results'
   // getter and setter methods
}

PizzaResult的代码片段:

@ManagedBean
@SessionScoped
public class PizzaResult {
   // injection of PizzaSearch
   @ManagedProperty(value="#{pizzaSearch}")
   private PizzaSearch pizzaSearch;
   // variables
   private List<PizzaObject> results;
   private int _chosenSize;
   private int _chosenQuantity;
   @PostConstruct
   public void initResults() {
      this.results = pizzaSearch.getResults();
   }
   // method to add the pizza object to the cart
   // a simple text output for testings
   public void addToCart(int chosenPizzaID) {
      System.out.println("chosen pizza ID: " + chosenPizzaID);
      System.out.println("chosen size:     " + _chosenSize);
      System.out.println("chosen quantity: " + _chosenQuantity);
   }
   // getter and setter methods
}

JSF输出页面的代码片段

<ui:repeat var="result" value="#{pizzaResult.results}">
   <h:form>
      <ul>
         <li><p>Name: #{result.pizza.name}</p></li>
         <li><p>ID: #{result.pizza.pizzaID}</p></li>
         <li>
            <p>Toppings:</p>
            <ui:repeat var="topping" value="#{result.toppingList}">
               <p>#{topping.toppingName}</p>
            </ui:repeat>
         </li>
         <li>
            <p>Sizes:</p>
            <h:selectOneRadio id="chosenSize" value="#{pizzaResult.chosenSize}">
               <f:selectItems value="#{result.sizeList} var="size" itemLabel="#{size.diameter}" itemValue="#{size.sizeID}"/>
            </h:selectOneRadio>
         </li>
         <li>
            <p>Quantity:</p>
            <h:selectOneListbox id="chosenQuantity" value="#{pizzaResult.chosenQuantity}" size="1">
               <f:selectItem id="quantity1" itemLabel="1x" itemValue="1">
               <f:selectItem id="quantity2" itemLabel="2x" itemValue="2">
            </h:selectOneListbox>
         </li>
         <li>
            <h:commandButton value="add to cart" action="#{pizzaResult.addToCart(result.pizza.pizzaID)}"/>
         </li>
      </ul>
   </h:form>
</ui:repeat>

我有一种感觉,这个问题将由变量chosenSize和chosenQuantity调用。但我不知道如何解决那个问题。我希望你能以某种方式帮助我。谢谢

我假设您使用的是JSF的Mojarra参考实现。

由于Mojarra中的错误,原始代码无法工作。简而言之,ui:repeat不维护其行的状态。

为了让它发挥作用,你必须:

  1. 切换到另一个实现,如ApacheMyFaces,该代码在其中工作(请参阅我的实现(
  2. 或将表单移动到ui:repeat之外
  3. 如该回答中所建议的:

    使用另一个迭代组件(例如<c:forEach><h:dataTable><t:dataList><p:dataList>等(

然而,像@user2314868建议的那样,简单地将表单移动到ui:repeat之外是行不通的。这是因为所有字段都是从表单中发布的。因此,每个h:selectOneRadio都会在更新模型值阶段更新#{pizzaResult.chosenSize}。因此,在调用应用程序阶段,只有最后一次更新才可见。与#{pizzaResult.chosenQuantity}类似。

为了使它发挥作用,我建议用值数组来替换像chosenSize这样的单个值。然后我们可以利用CCD_ 11状态变量的CCD_。

<h:form id="pizzasForm">
    <ui:repeat var="result" value="#{pizzaResult.results}" varStatus="loop">
        <ul>
            <li><p>Name: #{result.pizza.name}</p></li>
            <li><p>ID: #{result.pizza.pizzaID}</p></li>
            <li>
                <p>Sizes:</p> <h:selectOneRadio id="chosenSize"
                    value="#{pizzaResult.chosenSize[loop.index]}">
                    <f:selectItems value="#{result.sizeList}" var="size"
                        itemLabel="#{size.diameter}" itemValue="#{size.sizeID}" />
                </h:selectOneRadio>
            </li>
            <li>
                <p>Quantity:</p> <h:selectOneListbox id="chosenQuantity"
                    value="#{pizzaResult.chosenQuantity[loop.index]}" size="1">
                    <f:selectItem id="quantity1" itemLabel="1x" itemValue="1" />
                    <f:selectItem id="quantity2" itemLabel="2x" itemValue="2" />
                </h:selectOneListbox>
            </li>
            <li><h:commandButton value="add to cart"
                    action="#{pizzaResult.addToCart(loop.index)}"/></li>
        </ul>
    </ui:repeat>
</h:form>

PizzaResult:的变化

@ManagedBean
@SessionScoped
public class PizzaResult {
    // injection of PizzaSearch
    @ManagedProperty(value = "#{pizzaSearch}")
    private PizzaSearch pizzaSearch;
    // variables
    private List<PizzaObject> results;
    private int[] _chosenSize;
    private int[] _chosenQuantity;
    @PostConstruct
    public void initResults() {
        this.setResults(getPizzaSearch().getResults());
        int size = this.getResults().size();
        this._chosenSize = new int[size];
        this._chosenQuantity = new int[size];
    }
    // method to add the pizza object to the cart
    // a simple text output for testings
    public void addToCart(int index) {
        System.out.println("chosen pizza ID: " + results.get(index).getPizza().getPizzaID());
        System.out.println("chosen size:     " + getChosenSize()[index]);
        System.out.println("chosen quantity: " + getChosenQuantity()[index]);
    }
...

完整的工作示例可以在这里找到

要做的步骤:

步骤1:

Move the h:form outside the ui:repeat (In JSF)

步骤2:

Give some id to the form (In JSF)

步骤3:

update the form once add method exucuted
<h:commandButton value="add to cart" action="#{pizzaResult.addToCart(result.pizza.pizzaID)}" update="give form id name here"/>

第4步:

In addToCart() method, reset chosenPizzaID, _chosenSize and _chosenQuantity to 0
i.e 
chosenPizzaID=0
_chosenSize=0
_chosenQuantity=0

相关内容

  • 没有找到相关文章

最新更新