我再次使用Java Server Faces编写的pizza-search-programm需要一些帮助。
该计划: 用户可以通过输入表单来搜索比萨饼。过滤搜索是可能的,因为用户可以决定他是否搜索比萨饼名称,比萨饼ID或其他指定标准。该程序将生成一个SQL查询,该查询返回pizza对象并将其存储到对象列表中。 JSF页面通过ui:repeat标记迭代它们来显示披萨对象列表。将显示比萨饼名称,比萨饼ID,可用尺寸(显示为单选按钮)和可能数量列表。对于每个显示的披萨对象,都有一个“添加到购物车按钮”,用于在所选尺寸和数量的参数化值下将披萨添加到购物车。
问题: 几乎所有东西都正确显示。但是当在购物车上添加比萨饼时,会发生错误。如果用户搜索特定比萨饼,则通过将比萨饼ID,所选尺寸和所选数量提交给添加到购物车方法将没有问题。但是,当列表包含多于一个比萨饼对象时,通过提交比萨饼ID,所选尺寸和所选数量的正确值,可以仅将最后一个比萨饼正确地添加到购物车中。如果用户试图将其中一个上层比萨饼放入购物车,那么之前提交的尺寸和数量将被采用,前提是之前已经成功执行了“添加购物车动作”。如果不是用户选择的大小和数量,则不会提交0。
示例: 用户搜索“pizza salami”。他将其中的两个40英寸加到他的购物车上。 (selectedPizzaID:1; selectedSize:40; selectedQuantity 2)。一切都正确执行。但在此之后,用户搜索所有比萨饼。他想添加显示列表中的第一个披萨。这种比萨饼的尺寸仅为30英寸。他选择了30英寸的比萨饼中的3个,并点击“添加到购物车按钮”。该程序采用selectedSize和chosenQuantity的先前参数(selectedSize:40; selectedQuantity: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>
我觉得问题会被变量selectedSize和chosenQuantity调用。但我不知道如何解决这个问题。我希望你能以某种方式帮助我。谢谢!
答案 0 :(得分:0)
步骤:
第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
答案 1 :(得分:0)
我假设您使用Mojarra - JSF的参考实现。
由于this answer中描述的Mojarra中的错误,原始代码无效。简而言之,ui:repeat不会保持其行的状态。
为了使其正常运行,您必须:
ui:repeat
使用其他迭代组件(例如
<c:forEach>
,<h:dataTable>
,<t:dataList>
,<p:dataList>
等)
但是,只需在ui:repeat
之外移动表单,如@ user2314868建议不起作用。这是因为所有字段都是从表单中发布的。因此,每个h:selectOneRadio
在更新模型值阶段更新#{pizzaResult.chosenSize}
。因此,只有最后一次更新才会在Invoke Application阶段中显示。同样适用于#{pizzaResult.chosenQuantity}
。
为了使其正常工作,我建议将chooseSize这样的单个值替换为值数组。我们可以利用状态变量index
的{{1}}属性。
ui:repeat
<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
可以找到完整的工作示例here