当前位置: 首页 > 面试题库 >

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

余铭晨
2023-03-14
问题内容

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

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

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下一个请求,因此renderededit部分的属性为false,因此edit部分中的按钮将不会调用任何操作。您先前的问题已经回答了。

从理论上讲,标记Bean@ViewScoped应该可以解决此问题,因为在后续视图中它将保留Bean状态。但是,在您的特定情况下,有两个问题使其无法正常工作。

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

其次,由于JSF2(问题1718)中当前仍存在一个打开的错误,您的特定情况仍然无法正常工作,因为您有多个<h:form>处于不同rendered条件的条件都被附加到同一bean。这种特定情况将导致javax.faces.ViewState返回的响应中完全丢失。这将导致视图作用域的bean被垃圾回收并重新创建(profilePage默认值为main再次)。作为临时的解决方法,您需要将表单提取并合并为其中的一个表单profile.xhtml,作为first的直接子代<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");
    }

    // ...
}


 类似资料:
  • 问题内容: 为什么在下面的程序中不执行func3?在func1之后,不需要对func2进行评估,但是对于func3,不是吗? 问题答案: 您正在使用短路或。如果第一个参数为true,则整个表达式为true。 如果添加编译器使用的隐式括号可能会有所帮助 编辑 :正如Chris Jester-Young所说,这实际上是因为逻辑运算符必须从左到右的关联性: func1返回之后,它变为: 评估短路或后,它

  • 问题内容: 我不太确定这是什么意思或在做什么,有人可以详细说明吗? 问题答案: 它接受发送者引用的对象,并尝试将其转换为Player类型。Java对象是强类型的,这意味着您必须声明对象的类型。 如果发件人引用的对象不能转换为Player对象,则将为InvalidCast抛出异常。

  • 问题内容: 我创建了一个简单的Angular JS $ routeProvider解决测试应用程序。它给出以下错误: 如果有人可以确定我哪里出了问题,我将不胜感激。 index.html ResolveTest.js rt.html 问题答案: 问题在于,当您在$ routeProvider中也为rt.html指定相同的控制器时,您就在index.html的body标签上了。从body标记中删除控

  • 问题内容: JSF是否可以进行将同时执行的ajax调用(在开始新的调用之前不等待先前的调用完成)? 问题答案: 不,它们被规范明确地排队,没有任何例外。参见JSF 2规范的 第13.3.2章: 13.3.2 Ajax请求队列 在将所有Ajax请求发送到服务器之前,必须将它们放入客户端请求队列中,以确保按发送顺序处理Ajax请求。在队列中等待时间最长的请求是下一个要发送的请求。发送请求后,Ajax请

  • 这个函数我传入一个数组提示arr.map不是函数?

  • 1. 2. 如果我错了,请纠正我。谢谢大家!:) 根据我迄今为止的理解: < code>JNZ如果不等于零则跳转,它是否跳转取决于< code>ZF是否设置为1。如果是1,它不会跳。否则,它会跳起来。 根据我对代码#1的理解,< code >测试EAX,EAX将检查它是否为零。如果它不等于零(< code>ZF为0),它将跳转到地址00407190。 对于代码#2 将把EAX寄存器设置为0。它是否