我有一个JSF页面,它根据我的托管bean中名为 panels 的成员动态呈现一系列面板网格和嵌套元素,其中定义了所有元数据(如每个面板的标题,列) ,样式或每个字段的标签,输入类型和映射等)。其中的所有面板和字段都通过JSTL / core forEach循环呈现。现在我想根据用户的选择渲染一个面板。
简化的页面摘录如下:
<p:selectOneRadio id="radio1" value="#{myBean.selectPanel}" layout="grid" columns="1">
<f:selectItem itemLabel="Option1" itemValue="0" />
<f:selectItem itemLabel="Option2" itemValue="1" />
<p:ajax event="change" listener="#{myBean.handleIt()}" process="@this" update="@form"/>
</p:selectOneRadio>
<c:forEach var="panel" items="#{myBean.panels}">
<c:if test="#{not empty panel.render}">
<h:panelGrid id="#{panel.name}">
<c:forEach var="field" items="#{panel.fields}">
<h:outputLabel value="#{bundle[field.label]}" escape="false" for="#{field.name}"/>
<!-- input fields like input box or dropdown list are ignored here -->
</c:forEach>
</h:panelGrid>
</c:if>
</c:forEach>
虚拟面板初始化的托管bean
@ManagedBean
@ViewScoped
public class MyBean{
private List<Panel> panels = new ArrayList<Panel>();
public void initPanels() {
Panel p;
Field f;
p = new Panel();
//instantiate a Field by passing label and name
f = new Field("panel1_label1", "panel1_field1");
p.addField(f);
panels.add(p);
p = new Panel();
f = new Field("panel2_label1", "panel2_field1");
p.addField(f);
panels.add(p);
this.setSelectPanel(0);
}
...
}
首次加载页面时,一切看起来都很好,只显示选定的面板。但是当您选择单选按钮时,它始终显示第一个面板标签,但相应的输入字段始终正确呈现。
如果我将“id”属性添加到这样的标签中,那么我看到了正确的ID被分配。
<h:outputLabel id="#{'lbl_'.concat(field.name)}" value="#{bundle[field.label]}" escape="false" for="#{field.name}"/>
输出html标签将如下:
<label id="myForm:lbl_panel2_field1" for="myForm:panel2_field1">Panel1 Field1 Label</label>
这意味着TagHandler在构建UIViewRoot树时使用了正确的字段数据,并且在我调试它时(在调用 FaceletViewHandlingStrategy.buildView(FacesContext,UIViewRoot)之后)也证明了这一点。所以我的问题是,当渲染视图时,JSF在评估标签的“值”表达式时如何使用错误的字段对象?
有趣的是,如果我刷新此页面,无论我选择哪个面板,面板都会正确显示。
BTW我使用的是Spring Web Flow + JSF(2.2.8版)。 任何解释或帮助都表示赞赏。