我在pojo列表中有一个pojo列表,我试图在jsf 2.2.6和primefaces 4.0的数据表中以动态方式使用它。我认为我很接近,但我无法使其发挥作用。
这个想法是配置多轮高尔夫比赛。主要列表(注册)是所有具有姓名,差点因素等信息的玩家。注册列表中的列表是每轮的开球时间,起始洞等,它可以是1-4轮的任何地方,我只想显示在p:dataTable的列中一次一个。用户可以使用selectOneButton单击要查看的回合,它将动态更改为该数据。
关键思想是(1)selectOneButton和ajax触发标识表索引的属性的更改。 (2)JSTL帮助使EL表达式更短,更易读(3)通过主列表的典型数据表(4)EL将它们放在一起,尝试根据按钮选择的索引提取正确的轮次。 这是一个精简版,以显示问题但我不认为我遗漏了任何重要的东西。这是xhtml:
<c:set value="#{events.activeRoundIndex}" var="i"/>
<p:commandButton value="Update" action="#{events.regUpdateAll()}"
process="@form" update="@form" />
<div style="float: right">
<p:selectOneButton rendered="#{events.selectedEvent.noOfRounds gt 0}" value="#{events.activeRoundIndex}">
<f:selectItem itemLabel="1" itemValue="0"/>
<f:selectItem itemDisabled="#{events.selectedEvent.noOfRounds lt 2}" itemLabel="2" itemValue="1"/>
<f:selectItem itemDisabled="#{events.selectedEvent.noOfRounds lt 3}" itemLabel="3" itemValue="2"/>
<f:selectItem itemDisabled="#{events.selectedEvent.noOfRounds lt 4}" itemLabel="4" itemValue="3"/>
<f:ajax execute="@form" render="@form"/>
</p:selectOneButton>
</div>
<p:dataTable value="#{events.registrationList}" var="item" rowIndexVar="rowIndex">
<p:columnGroup type="header">
<p:row>
<p:column headerText="First Name" rowspan="2"/>
<p:column headerText="Last Name" rowspan="2"/>
<p:column headerText="Round #{i+1}" colspan="2"/>
</p:row>
<p:row>
<p:column headerText="Tee Time"/>
<p:column headerText="Start Hole"/>
</p:row>
</p:columnGroup>
<p:column>#{item.playerId.firstName}</p:column>
<p:column>#{item.playerId.lastName}</p:column>
<p:column>
<p:inputText value="#{item.roundList.get(i).teeTime}">
<f:convertDateTime type="time" timeStyle="short"/></p:inputText>
</p:column>
<p:column>
<p:inputText value="#{item.roundList.get(i).startingHole}"/>
</p:column>
</p:dataTable>
没有崩溃,数据格式正确,只是没有从正确的位置检索
任何方向都将非常感谢
BTW这个问题被重写了,因为我无法弄清楚放置较小代码片段的格式。
更新:在我的代码的另一个区域证明了这个概念,并进一步诊断出问题。更新模型值阶段(4)正在更新列表中的错误索引。即如果我正在查看第1洞(索引0)并点击第2洞,它实际上更新了索引1处的属性而不是JSF阶段4(Mojara)中的0。我认为这只能由于上面显示的代码而发生。任何人都可以看到我做错了什么或是系统错误?
使用完整而简单的代码示例进一步更新,以演示此问题。通过使P1可编辑和P2显示,您可以看到在没有用户输入的情况下更改了属性。我相信这是一个系统错误,但希望我错了,因为我真的需要这个工作。这是代码:
<p:panelGrid>
<p:row>
<p:column>Name</p:column>
<p:column>Selected Index</p:column>
<p:column>P1</p:column>
<p:column>P2</p:column>
</p:row>
<c:forEach items="#{test.list}" var="item2">
<c:set value="#{test.getMinor(item2)}" var="sub"/>
<p:row>
<p:column>#{item2.name}</p:column>
<p:column>#{test.selectedIndex}</p:column>
<p:column><p:inputText value="#{sub.p1}"/></p:column>
<p:column>#{sub.p2}</p:column>
</p:row>
</c:forEach>
</p:panelGrid>
</h:form>
和SessionScoped JAVA代码
public class Test {
private List<ItemHolder> list;
private int selectedIndex=0;
public Test() {
list = new ArrayList();
list.add(new ItemHolder());
}
public void doNothingAjax() {
}
public Item getMinor(ItemHolder holder) {
return holder.getItems().get(selectedIndex);
}
//Getters & Setters
public class ItemHolder {
private String name;
List<Item> items;
public ItemHolder() {
name = "Test";
items = new ArrayList();
items.add(new Item("index 0",0,0));
items.add(new Item("index 1",1,1));
}
//getters and setters
public class Item {
private String label;
private int p1; //property 1
private int p2; //property 2
public Item(String label, int p1, int p2) {
this.label = label;
this.p1 = p1;
this.p2 = p2;
}
//Getters and Setters
非常感谢任何帮助。如果是系统错误,任何针对变通方法的建议也会有所帮助。我的想法已经不多了。
谢谢,约翰
答案 0 :(得分:2)
c:forEach
和c:set
导致您的问题。请参阅various上的articles subject。 (另见BalusC's comment)
基本上,c:
标记不保存状态(不是jsf组件树的一部分)并且导致你注意到的内容:
更新模型值阶段(4)正在更新列表中的错误索引。
我没有检查,但我打赌第4阶段总是更新最后一个('次要')sub.p1
。这是因为到阶段4运行时,sub
(最后'次')是一个常量,因为它在每个c:forEach
迭代期间的状态不会保存在组件树中。
建议?
c:
标记。c:forEach
使用ui:repeat
c:set
,请使用完整路径#{item2.items.get(test.selectedIndex).p1}
。 (可能需要对基础数据结构进行重组)