繁体   English   中英

JSF - Ajax调用 - 这段代码有什么问题?

[英]JSF - Ajax call - What is it wrong on this code?

我认为解决此问题的最佳方法是粘贴我的代码:

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>           

如果我先单击“ 编辑”按钮而不是“ 确认编辑” ,我会尝试获取(作为结果)带有标签的页面最终即时通知此处不会发生这种情况。 我点击编辑按钮然后,如果我点击确认编辑 ,没有任何反应。

我错了什么? 干杯

更新版本

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>

好吧,这变得复杂了。 是否将调用UICommand操作还取决于组件或其父项之一的rendered属性的结果。 由于bean位于请求范围内,因此profilePage在下一个请求中默认返回main ,因此edit部分的rendered属性的计算结果为false ,因此edit部分中的按钮不会调用任何操作。 这已在您之前的问题中得到解答。

理论上,标记bean @ViewScoped应该解决这个问题,因为它在后续视图中保留了bean状态。 但是,在您的特定情况下,有两个问题会阻止它正常工作。

首先,您使用的是@ManagedProperty ,它指的是一个较短范围内的值( #{param}基本上是请求范围的)。 您需要将profilePage拆分为另一个bean并标记此@ViewScoped

其次,由于JSF2中当前仍然存在漏洞( 问题1718 ),您的特定情况仍然无效,因为您在不同的rendered条件中有多个<h:form> ,它们都附加到同一个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");
    }

    // ...
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM