preRenderView禁用ajax

时间:2012-11-26 17:47:30

标签: java jsf jsf-2

<ui:composition template="/WEB-INF/templates/base.xhtml"
                xmlns="http://www.w3.org/1999/xhtml"
                xmlns:ui="http://java.sun.com/jsf/facelets"
                xmlns:h="http://java.sun.com/jsf/html"
                xmlns:f="http://java.sun.com/jsf/core"
                xmlns:p="http://primefaces.org/ui">    
    <ui:define name="metadata">
        <f:metadata>
            <f:event type="preRenderView" listener="#{resetPassword.loadUser}" />
            <f:viewParam name="user" value="#{resetPassword.user}" />
        </f:metadata>
    </ui:define>

    <ui:define name="content">
        <h:form rendered="#{resetPassword.user != null}">
            <h:panelGrid class="form_panel" columns="2" width="596px">
                <h:outputLabel class="form_label" for="password" value="#{base['resetPassword.password']}" />
                <h:inputSecret class="form_inputText" id="password" value="#{resetPassword.password}">
                    <f:ajax event="keyup" execute="password" listener="#{resetPassword.validatePassword}" render="scorePanel complexity" />
                </h:inputSecret>

                (...) // Other labels and inputfields, no ajax
            </h:panelGrid>
        </h:form>
    </ui:define>
</ui:composition> 

我已阅读preRenderViewajax - 调用相关的许多问题。我遇到的主要问题是postback问题。虽然在我的情况下,ajax根本不会触发preRenderView。如果没有整个f:event - 标记,我的ajax - 调用确实有效。

resetPassword.loadUser()将设置resetPassword.user,这不是null。我需要使用preRenderView代替@PostConstruct来填充f:viewParam。提交表单时需要此参数。

为什么我的ajax - 事件会在定义<f:event type="preRenderView" />时中断?

注意:模板中的<ui:insert name="metadata" />位于<h:head>内。

更新

正如BalusC评论的那样,这部分代码中不会出现这个问题。

public void loadUser(ComponentSystemEvent event) {
    if(!FacesContext.getCurrentInstance().isPostback()) {
        user = (hash != null) ? userService.getByIdAndPwdResetHash(userId, hash) : null;
    }
}

此代码可能会返回null但不会(因为正在加载我的表单)。

public void validatePassword(AjaxBehaviorEvent event) {
    System.out.println("Ajax works"); // Just for testing purposes so far
}

我不知道要进一步添加什么,因为这几乎都是相关的代码。

1 个答案:

答案 0 :(得分:4)

#{resetPassword}是请求作用域并且在bean(post)构造期间未初始化user属性时,此构造将失败。

JSF将在应用请求值阶段期间,即在处理提交的值之前重新评估输入组件的rendered属性(这也包括其所有父组件),作为防止篡改请求的一部分。在您的情况下,不会呈现父表单,因此不会处理所有输入组件。

你基本上有两个选择:

  1. 使bean @ViewScoped(或CDI等效@ConversationScoped)。这种方式只要你与同一个视图(相应的对话)进行交互就会存在。

  2. 在(post)构造函数中执行user的初始化。预渲染视图为时已晚。由于您的bean已经是请求范围,只需使用@ManagedProperty(或其本地CDI等效项; Google在“@HttpParam”上有结果)。

  3. 另见:


    对具体问题

    无关,在动作(侦听器)方法中执行验证不是正确的方法。不是<f:ajax listener>,而是使用您通过输入组件的Validator属性或嵌套的validator引用的普通<f:validator>