我认为解决此问题的最佳方法就是粘贴我的代码:
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>
如果我先点击 编辑按钮 和比 确认编辑 ,我试图获得(作为结果)的页面标签 FINALLY我在这里 不幸的是,这并不发生。我单击“ 编辑”按钮 ,然后单击“ 确认编辑” ,则什么也没有发生。
我怎么了 干杯
用新版本更新
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; } }
<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>
<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>
<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>
好吧,那变得复杂了。是否UICommand将调用该操作还取决于rendered组件或其父项之一的属性的结果。由于Bean在请求范围内,因此profilePage默认值返回到main下一个请求,因此renderededit部分的属性为false,因此edit部分中的按钮将不会调用任何操作。您先前的问题已经回答了。
UICommand
rendered
profilePage
main
false
从理论上讲,标记Bean@ViewScoped应该可以解决此问题,因为在后续视图中它将保留Bean状态。但是,在您的特定情况下,有两个问题使其无法正常工作。
@ViewScoped
首先,您使用的是@ManagedProperty,它指的是范围较短的值(#{param}基本上是请求范围内的值)。您将需要将其拆分profilePage为另一个bean并进行标记@ViewScoped。
@ManagedProperty
#{param}
其次,由于JSF2(问题1718)中当前仍存在一个打开的错误,您的特定情况仍然无法正常工作,因为您有多个<h:form>处于不同rendered条件的条件都被附加到同一bean。这种特定情况将导致javax.faces.ViewState返回的响应中完全丢失。这将导致视图作用域的bean被垃圾回收并重新创建(profilePage默认值为main再次)。作为临时的解决方法,您需要将表单提取并合并为其中的一个表单profile.xhtml,作为first的直接子代<h:panelGroup>。
<h:form>
javax.faces.ViewState
<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"); } // ... }