preRenderView禁用Ajax [英] preRenderView disables ajax

查看:100
本文介绍了preRenderView禁用Ajax的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

<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调用确实可以正常工作.

I have read about a lot of problems with preRenderView in combination with ajax-calls. The main problem I have come across is the postback issue.Though, in my case, ajax won't fire at all with the preRenderView. Without the whole f:event-tag, my ajax-call does work correct.

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

resetPassword.loadUser() will set resetPassword.user, which is NOT null. I need to use the preRenderView instead of @PostConstruct in order to fill the f:viewParam. This param is needed when the form is submitted.

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

Why does my ajax-event break when <f:event type="preRenderView" /> is defined?

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

Note: <ui:insert name="metadata" /> in the template is located inside <h:head>.

更新

正如BalusC所说,该问题在此部分代码中不可见.

As BalusC commented, the issue is not visible in this part of the code.

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

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

This code might return null but doesn't (as my form is being loaded).

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

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

I don't know what to add further, as this pretty much is all relevant code.

推荐答案

当在bean的(post)构造过程中请求#{resetPassword}的作用域且未初始化user属性时,此构造将失败.

This construct will fail when the #{resetPassword} is request scoped and the user property is not initialized during bean's (post)construction.

JSF将在应用请求值阶段,即在处理提交的值之前重新评估输入组件(还包括其所有父组件)的rendered属性,以防篡改请求.在您的情况下,不会呈现父表单,因此不会处理所有输入组件.

JSF will during apply request values phase namely re-evaluate the rendered attribute of an input component (this also includes all of its parent components) before processing the submitted value, as part of safeguard against tampered requests. In your case, the parent form is not rendered and thus all input components won't be processed.

您基本上有2个选择:

  1. 制作bean @ViewScoped(或等效于CDI的@ConversationScoped).这样,只要您与同一个视图进行交互(重新对话),它就可以存在.

  1. Make the bean @ViewScoped (or the CDI equivalent @ConversationScoped). This way it lives as long as you're interacting with the same view (resp. conversation).

在(post)构造函数中执行user的初始化.渲染前视图为时已晚.由于您的bean已在请求范围内,因此只需使用@ManagedProperty(或它的本地CDI等效项; Google在"@HttpParam"上显示结果).

Perform the initialization of user in (post)constructor. The pre render view is too late. As your bean is request scoped already, just use @ManagedProperty (or its homegrown CDI equivalent; Google has results on "@HttpParam").

另请参见:

  • commandButton/commandLink/ajax action/listener方法未调用或输入值未更新-第5点适用于您的情况
  • ViewParam与@ManagedProperty(值=#{param.id} ")-更好地了解其生命周期中的差异
  • See also:

    • commandButton/commandLink/ajax action/listener method not invoked or input value not updated - Point 5 applies to your case
    • @Inject to pass params to a CDI @Named bean via URL - Contains a concrete example of custom @HttpParam annotation as CDI substitution of JSF @ManagedProperty
    • ViewParam vs @ManagedProperty(value = "#{param.id}") - to understand the difference in its lifecycle better
    • 不相关与具体问题无关,在action(listener)方法中执行验证不是正确的方法.代替<f:ajax listener>,使用普通的Validator,您可以通过输入组件的validator属性或嵌套的<f:validator>引用它.

      Unrelated to the concrete question, performing validation in an action(listener) method isn't the right approach. Instead of <f:ajax listener>, use a normal Validator which you reference by input component's validator attribute or a nested <f:validator>.

      这篇关于preRenderView禁用Ajax的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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