我认为解决此问题的最佳方法就是粘贴我的代码:
Selector bean
@ManagedBean(name="selector")
@RequestScoped
public class Selector {
@ManagedProperty(value="#{param.page}")
private String page;
private String profilePage;
@PostConstruct
public void init() {
if(profilePage==null || profilePage.trim().isEmpty()) {
this.profilePage="main";
}
if(page==null || page.trim().isEmpty()) {
this.page="homepage";
}
}
public String getProfilePage() { System.out.println("GET ="+profilePage); return profilePage; }
public void setProfilePage(String profilePage) { this.profilePage=profilePage; }
public String getPage() { return page; }
public void setPage(String page) { this.page=page; }
}
profile.xhtml
<h:panelGroup layout="block" id="profileContent">
<h:panelGroup rendered="#{selector.profilePage=='main'}">
<ui:include src="/profile/profile_main.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{selector.profilePage=='edit'}">
<ui:include src="/profile/profile_edit.xhtml" />
</h:panelGroup>
</h:panelGroup>
profile_main.xhtml
<h:form id="formProfileMain" prependId="false">
<h:panelGroup layout="block">
<h:outputScript name="jsf.js" library="javax.faces" target="head" />
<h:outputLabel value="MAIN" />
<h:panelGroup layout="block" >
<h:commandButton value="Edit Button">
<f:setPropertyActionListener target="#{selector.profilePage}" value="edit" />
<f:ajax event="action" render=":profileContent"/>
</h:commandButton>
</h:panelGroup>
</h:panelGroup>
</h:form>
profile_edit.xhtml
<h:panelGroup layout="block" id="profileEditContent">
<h:panelGroup rendered="#{selector.profilePage=='edit'}">
<h:form id="formProfileEdit" prependId="false">
<h:panelGroup layout="block">
<h:outputScript name="jsf.js" library="javax.faces" target="head" />
<h:outputLabel value="EDIT" />
<h:panelGroup layout="block">
<h:commandButton value="Confirm Edit">
<f:setPropertyActionListener target="#{selector.profilePage}" value="editConfirm" />
<f:ajax event="action" render=":profileEditContent"/>
</h:commandButton>
<h:commandButton value="Back">
<f:setPropertyActionListener target="#{selector.profilePage}" value="main" />
<f:ajax event="action" render=":profileEdit"/>
</h:commandButton>
</h:panelGroup>
</h:panelGroup>
</h:form>
</h:panelGroup>
<h:panelGroup rendered="#{selector.profilePage=='editConfirm'}">
<h:outputLabel value="FINALLY IM HERE" />
</h:panelGroup>
</h:panelGroup>
如果我先点击修改按钮,然后点击确认修改,我会尝试获取(结果)带有标签最终IM HERE <的页面/强> 不幸的是,这并没有发生。我点击修改按钮,之后,如果我点击确认修改,则不会发生任何事情。
我错了什么?干杯
更新新版
bean
@ManagedBean
@ViewScoped
public class ProfileSelector {
private String profilePage;
@PostConstruct
public void init() {
if(profilePage==null || profilePage.trim().isEmpty()) {
this.profilePage="main";
}
}
public String getProfilePage() { return profilePage; }
public void setProfilePage(String profilePage) { this.profilePage=profilePage; }
}
profile.xhtml
<h:panelGroup layout="block" id="profileContent">
<h:form id="formProfile" prependId="false">
<h:outputScript name="jsf.js" library="javax.faces" target="head" />
<h:panelGroup rendered="#{profileSelector.profilePage=='main'}">
<ui:include src="/profile/profile_main.xhtml" />
</h:panelGroup>
<h:panelGroup rendered="#{profileSelector.profilePage=='edit'}">
<ui:include src="/profile/profile_edit.xhtml" />
</h:panelGroup>
</h:form>
</h:panelGroup>
profile_main.xhtml
<h:panelGroup layout="block">
<h:outputLabel value="MAIN" />
<h:panelGroup layout="block">
<h:commandButton value="Edit Button">
<f:setPropertyActionListener target="#{profileSelector.profilePage}" value="edit" />
<f:ajax event="action" render=":profileContent"/>
</h:commandButton>
</h:panelGroup>
</h:panelGroup>
profile_edit.xhtml
<h:panelGroup layout="block" id="profileContentEdit">
<h:panelGroup rendered="#{profileSelector.profilePage=='edit'}">
<h:panelGroup layout="block">
<h:outputLabel value="EDIT" />
<h:panelGroup layout="block" styleClass="profilo_3">
<h:commandButton value="Confirm Edit">
<f:setPropertyActionListener target="#{profileSelector.profilePage}" value="editConfirm" />
<f:ajax event="action" render=":profileContentEdit"/>
</h:commandButton>
<h:commandButton value="Back">
<f:setPropertyActionListener target="#{profileSelector.profilePage}" value="main" />
<f:ajax event="action" render=":profileContent"/>
</h:commandButton>
</h:panelGroup>
</h:panelGroup>
</h:panelGroup>
<h:panelGroup rendered="#{profileSelector.profilePage=='editConfirm'}">
<h:outputLabel value="FINALLY Im HERE" />
</h:panelGroup>
</h:panelGroup>
答案 0 :(得分:5)
UICommand
操作还取决于组件的rendered
属性或其父项之一的结果。由于bean位于请求范围内,profilePage
在下一个请求中默认返回main
,因此编辑部分的rendered
属性评估false
,因此按钮位于编辑部分不会调用任何操作。这已在您的previous question中得到解答。
理论上,标记bean @ViewScoped
应该解决这个问题,因为它在后续视图中保留了bean状态。但是,在您的特定情况下,有两个问题会阻止它正常工作。
首先,您使用的是@ManagedProperty
,它指的是一个较短范围内的值(#{param}
基本上是请求范围的)。您需要将profilePage
拆分为另一个bean并标记此@ViewScoped
。
其次,由于JSF2(issue 1718)中当前仍然存在漏洞,您的特定情况仍然不起作用,因为您在不同的<h:form>
条件下有多个rendered
附在同一个bean上。这种特定情况会导致返回的响应中javax.faces.ViewState
完全丢失。这将导致视图范围bean被包含并重新创建(并且profilePage
默认为main
)。作为临时解决方法,您需要在profile.xhtml
中将表单提取并合并为一个表单,作为第一个<h:panelGroup>
的直接子项。
更新:如果您唯一担心的是要将bean连接到彼此,那么您可以按如下方式拆分bean:
@ManagedBean
@RequestScoped
public class Selector {
@ManagedProperty(value="#{param.page}")
private String page;
@ManagedProperty(value="#{profileSelector}")
private ProfileSelector profileSelector;
// ...
}
@ManagedBean
@ViewScoped
public class ProfileSelector {
private String profilePage;
// ...
}
然后可以通过这种方式在请求范围bean中访问视图范围的bean。
或者,如果确实希望拥有单个bean,您可以将解决方法替换为@ManagedProperty
,如下所示:
@ManagedBean
@ViewScoped
public class Selector {
private String page;
private String profilePage;
@PostConstruct
public void init() {
page = FacesContext.getCurrentInstance().getRequestParameterMap().get("page");
}
// ...
}