JSF - Ajax调用 - 这是什么错在这个code? [英] JSF - Ajax call - What is it wrong on this code?

查看:136
本文介绍了JSF - Ajax调用 - 这是什么错在这个code?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我觉得要解决这个问题的最好办法就是贴上我的code:

选择绿豆

  @ManagedBean(NAME =选择)
@RequestScoped
公共类选择{
    @ManagedProperty(值=#{param.page})
    私人字符串的页面;
    私人字符串profilePage;

    @PostConstruct
    公共无效的init(){
        如果(profilePage == NULL || profilePage.trim()的isEmpty()){
            this.profilePage =主;
        }

        如果(页面==空|| page.trim()。的isEmpty()){
            this.page =主页;
        }
    }

    公共字符串getProfilePage(){的System.out.println(GET =+ profilePage);返回profilePage; }
    公共无效setProfilePage(字符串profilePage){this.profilePage = profilePage; }

    公共字符串GETPAGE(){返回页面; }
    公共无效setPage(字符串页){this.page =页面; }
}
 

profile.xhtml

 < H:panelGroup中布局=块ID =profileContent>
    < H:panelGroup中呈现=#{selector.profilePage =='主'}>
        <用户界面:包括SRC =/型材/ profile_main.xhtml/>
    < /小时:panelGroup中>

    < H:panelGroup中呈现=#{selector.profilePage =='编辑'}>
        <用户界面:包括SRC =/型材/ profile_edit.xhtml/>
    < /小时:panelGroup中>
< /小时:panelGroup中>
 

profile_main.xhtml

 < H:格式ID =formProfileMainprependId =假>
    < H:panelGroup中布局=块>
        < H:outputScript名=jsf.js库=javax.faces目标=头/>

        < H:outputLabel值=主/>

        < H:panelGroup中布局=块>
            < H:的commandButton值=编辑按钮>
                < F:setPropertyActionListener目标=#{selector.profilePage}值=编辑/>
                < F:Ajax事件=动作渲染=:profileContent/>
            < / H:的commandButton>
        < /小时:panelGroup中>
    < /小时:panelGroup中>
< /小时:形式GT;
 

profile_edit.xhtml

 < H:panelGroup中布局=块ID =profileEditContent>
    < H:panelGroup中呈现=#{selector.profilePage =='编辑'}>
        < H:格式ID =formProfileEditprependId =假>
            < H:panelGroup中布局=块>
                < H:outputScript名=jsf.js库=javax.faces目标=头/>

                < H:outputLabel值=编辑/>

                < H:panelGroup中布局=块>
                    < H:的commandButton值=确认编辑>
                        < F:setPropertyActionListener目标=#{selector.profilePage}值=editConfirm/>
                        < F:Ajax事件=动作渲染=:profileEditContent/>
                    < / H:的commandButton>

                    < H:的commandButton值=后退>
                        < F:setPropertyActionListener目标=#{selector.profilePage}值=主/>
                        < F:Ajax事件=动作渲染=:profileEdit/>
                    < / H:的commandButton>
                < /小时:panelGroup中>
            < /小时:panelGroup中>
        < /小时:形式GT;
    < /小时:panelGroup中>

    < H:panelGroup中呈现=#{selector.profilePage =='editConfirm'}>
        < H:outputLabel值=终于我在这里/>
    < /小时:panelGroup中>
< /小时:panelGroup中>
 

如果我先点击修改按钮并比对确认修改,我试图获得(作为结果)的页面标签的最后我在这里 不幸的是,这并不发生。我点击修改按钮之后,如果我点击确认修改,没有发生。

我是谁错了?干杯

更新为新的版本

  @ManagedBean
@ViewScoped
公共类ProfileSelector {
    私人字符串profilePage;

    @PostConstruct
    公共无效的init(){
        如果(profilePage == NULL || profilePage.trim()的isEmpty()){
            this.profilePage =主;
        }
    }

    公共字符串getProfilePage(){返回profilePage; }
    公共无效setProfilePage(字符串profilePage){this.profilePage = profilePage; }
}
 

profile.xhtml

 < H:panelGroup中布局=块ID =profileContent>
    < H:格式ID =formProfileprependId =假>
        < H:outputScript名=jsf.js库=javax.faces目标=头/>

        < H:panelGroup中呈现=#{profileSelector.profilePage =='主'}>
            <用户界面:包括SRC =/型材/ profile_main.xhtml/>
        < /小时:panelGroup中>

        < H:panelGroup中呈现=#{profileSelector.profilePage =='编辑'}>
            <用户界面:包括SRC =/型材/ profile_edit.xhtml/>
        < /小时:panelGroup中>
    < /小时:形式GT;
< /小时:panelGroup中>
 

profile_main.xhtml

 < H:panelGroup中布局=块>
    < H:outputLabel值=主/>

    < H:panelGroup中布局=块>
        < H:的commandButton值=编辑按钮>
            < F:setPropertyActionListener目标=#{profileSelector.profilePage}值=编辑/>
            < F:Ajax事件=动作渲染=:profileContent/>
        < / H:的commandButton>
    < /小时:panelGroup中>
< /小时:panelGroup中>
 

profile_edit.xhtml

 < H:panelGroup中布局=块ID =profileContentEdit>
    < H:panelGroup中呈现=#{profileSelector.profilePage =='编辑'}>
        < H:panelGroup中布局=块>
            < H:outputLabel值=编辑/>

            < H:panelGroup中布局=块的styleClass =profilo_3>
                < H:的commandButton值=确认编辑>
                    < F:setPropertyActionListener目标=#{profileSelector.profilePage}值=editConfirm/>
                    < F:Ajax事件=动作渲染=:profileContentEdit/>
                < / H:的commandButton>

                < H:的commandButton值=后退>
                    < F:setPropertyActionListener目标=#{profileSelector.profilePage}值=主/>
                    < F:Ajax事件=动作渲染=:profileContent/>
                < / H:的commandButton>
            < /小时:panelGroup中>
        < /小时:panelGroup中>
    < /小时:panelGroup中>

    < H:panelGroup中呈现=#{profileSelector.profilePage =='editConfirm'}>
        < H:outputLabel值=终于我在这里/>
    < /小时:panelGroup中>
< /小时:panelGroup中>
 

解决方案

嗯,这变得复杂。无论是 UICommand 的行动也将被调用取决于组件的渲染属性的结果,或它的某个父。因为bean是请求范围 profilePage 默认回到中的下一个请求,因此编辑小节评估,这样的按钮编辑区的渲染属性不会调用任何动作。这在你的<一被回答href="http://stackoverflow.com/questions/4291849/jsf-can-postconstruct-block-setter-method-by-using-an-ajax-call">$p$pvious问题。

在理论上,标志着豆 @ViewScoped 要解决这个问题,因为它保留了Bean状态在随后的意见。然而,在特定的情况下,有两个问题,其中价值无法正常工作p $ pvents它。

首先,您使用的是 @ManagedProperty 这是指一个值,它是一个较短的范围,(在#{参数} 基本上是请求范围)。您需要分割 profilePage 成另一种豆科和纪念这个 @ViewScoped

其次,由于目前仍处于打开状态的bug JSF2(问题1718 )您的特定情况下,仍然不能工作,因为你有多个&LT; H:形式GT; 在不同的渲染状态,可以所有连接到同一个bean。这种具体的情况将导致 javax.faces.ViewState 在返回的响应是完全缺失的。这将导致视图范围的bean被garbaged和重建(和 profilePage 默认为再次)。作为临时解决办法,你需要提取和合并的 profile.xhtml 的形式为一体的形式,作为第一个&LT直接子; H: panelGroup中&GT;


更新:如果你唯一关心的是,你要豆类相互连接,那么你可能分裂豆如下:

  @ManagedBean
@RequestScoped
公共类选择{
    @ManagedProperty(值=#{param.page})
    私人字符串的页面;

    @ManagedProperty(值=#{profileSelector})
    私人ProfileSelector profileSelector;

    // ...
}
 


  @ManagedBean
@ViewScoped
公共类ProfileSelector {
    私人字符串profilePage;

    // ...
}
 

视图范围的bean是那么访问请求范围的bean这种方式。

或者,如果你的真正的希望有一个bean,你可以作为一种解决方法也替换 @ManagedProperty 如下:

  @ManagedBean
@ViewScoped
公共类选择{
    私人字符串的页面;
    私人字符串profilePage;

    @PostConstruct
    公共无效的init(){
        页= FacesContext.getCurrentInstance()getRequestParameterMap()获得(网页)。
    }

    // ...
}
 

I think the best way to resolve this problem is just to paste my 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>           

If i click first on Edit Button and than on Confirm Edit, i attempt to get (as result) the page with the label FINALLY IM HERE Unfortunatly this doesnt happen. I click on Edit Button and after, if i click on Confirm Edit, nothing happen.

What am I wrong? Cheers

UPDATE WITH NEW VERSION

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>

解决方案

Well, that gets complicated. Whether the UICommand action will be invoked also depends on the result of the rendered attribute of the component or one of its parents. Because the bean is in the request scope the profilePage defaults back to main in the next request, so the rendered attribute of the edit section evaluates false, so the buttons in the edit section will not invoke any actions. This has been answered in your previous question.

In theory, marking the bean @ViewScoped should fix this because it retains the bean state in subsequent views. However, in your particular case there are two problems which prevents it from working properly.

First, you're using a @ManagedProperty which refers to a value which is in a shorter scope (the #{param} is basically request scoped). You would need to split the profilePage into another bean and mark this @ViewScoped.

Second, due to a currently still open bug in JSF2 (issue 1718), your particular case would still not work because you have multiple <h:form> in a different rendered condition which are all attached to the same bean. This specific situation would lead to javax.faces.ViewState being completely missing in the returned response. This will cause the view scoped bean to be garbaged and recreated (and the profilePage defaults to main again). As a temporary workaround, you need to extract and merge the forms into one form in profile.xhtml, as direct child of the first <h:panelGroup>.


Update: If your sole concern is that you want to connect the beans to each other, then you could split the beans as follows:

@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;

    // ...
}

The view scoped bean is then accessible in the request scoped bean this way.

Or, if you really want to have a single bean, you can as a workaround also replace @ManagedProperty as follows:

@ManagedBean
@ViewScoped
public class Selector {
    private String page;
    private String profilePage;

    @PostConstruct
    public void init() {
        page = FacesContext.getCurrentInstance().getRequestParameterMap().get("page");
    }

    // ...
}

这篇关于JSF - Ajax调用 - 这是什么错在这个code?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆