问题
I have the below Test.xhtml where i can select mode as Sea/Air. I don't want to load the all the 4 pages(Page1.xhtml, Page2.xhtml, Page3.xhtml, Page4.xhtml) into the jsf view tree. In my scenario, mode once selected and saved that can not be changed to other mode. The saved mode will be shown as view mode. Since at any point of time i need only 2 files (Page1.xhtml, Page2.xhtml (or) Page3.xhtml, Page4.xhtml)... I am using the JSTL tag handler for dynamic including the pages. the below thing is working fine. But i am not able to understand how the rendering working.
Test.xhtml
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<h:head><title>JSF And JSTL</title>
<link href="../css/styles.css"
rel="stylesheet" type="text/css"/>
</h:head>
<h:body>
<div align="center">
<h:form id="form1">
<h:panelGrid columns="2">
<h:outputLabel value="Select Mode"/>
<h:selectOneMenu id="selectPageId" value="#{testBean.selectedMode}">
<f:selectItem itemLabel="Select" />
<f:selectItem itemLabel="Sea" itemValue="sea" />
<f:selectItem itemLabel="Air" itemValue="air" />
<f:ajax execute="@this" render="pageGroup"/>
</h:selectOneMenu>
</h:panelGrid>
<h:panelGroup id="pageGroup">
<c:if test="#{'sea' eq testBean.selectedMode}">
<ui:include src="Page1.xhtml" />
<ui:include src="Page2.xhtml" />
</c:if>
<c:if test="#{'air' eq testBean.selectedMode}">
<ui:include src="Page3.xhtml" />
<ui:include src="Page4.xhtml" />
</c:if>
</h:panelGroup>
</h:form>
</div>
</h:body>
</html>
TestBean.java
package com.test;
@ManagedBean(name = "testBean")
@ViewScoped
public class TestBean {
private String selectedMode;
public String getSelectedMode() {
return selectedMode;
}
public void setSelectedMode(String selectedMode) {
this.selectedMode = selectedMode;
}
}
Updated Again
Please help to clarify the below.
When i send a request first time to access the Test.xhtml
, the jsf view (UIViewRoot
) gets created. Since testBean.selectedMode
by default is null.. this created view would not contain any component details of <c:if>
and <ui:include>
which are inside of <h:panelGroup id="pageGroup">
.
After that when i send a second request(ajax postback) by selecting the mode as sea, the UIViewRoot
gets created again for the request in the Restore View Phase. While UIViewRoot
creation for this request in Restore View Phase, the tag handlers(<c:xxx>, <f:xxx>, <ui:include>
) will get executed.
Since the selected value 'sea' will be updated to model(TestBean.java
) only in Update Model Values Phase, in the Restore View Phase the EL #{testBean.selectedMode}
will be evaluated to null.
So in my example Test.xhtml page the both tag handlers (<c:if test="#{'sea' eq testBean.selectedMode}">
and <c:if test="#{'air' eq testBean.selectedMode}">
) will be evaluated to false. So the UIViewRoot
does not contain any information related to the components inside <h:panelGroup id="pageGroup">
.
Even though the UIViewRoot
does not contain the components information inside the <h:panelGroup id="pageGroup">
, How JSF able to render the included pages(<ui:include src="Page1.xhtml" />,<ui:include src="Page2.xhtml" />
) successfully?
I am not sure how JSF rendering happening here. While Rendering, Is JSF re-creating the component tree for the particular rendering part(<h:panelGroup id="pageGroup">
).?
Note: The example is working fine when i select mode as sea/air. The corresponding parts are rendering correctly.
来源:https://stackoverflow.com/questions/30490445/how-jstl-tags-evaluated-in-jsf-2-1-for-the-below