【问题标题】:Programatically adding Ajax Behaviour - "Mojarra is not defined"以编程方式添加 Ajax 行为 - “未定义 Mojarra”
【发布时间】:2013-11-26 07:25:54
【问题描述】:

我有一个使用动态表单的页面,我在其中以编程方式创建组件树(在这个问题中没有争议) 我需要呈现的一些输入控件需要一个 ajax 处理程序。

xhtml 片段(由来自另一个片段的<ui:include> 包含)是:

<ui:composition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:p="http://xmlns.jcp.org/jsf/passthrough">

    <h:panelGroup id="id_Group1" binding="#{questionaire.group1}" layout="block"/>

</ui:composition>

基于其他 SO anwsers,我有以下 bean 代码:

   public HtmlPanelGroup getGroup1() {

        // irrelevant code omitted

        HtmlSelectOneRadio selectUI = new HtmlSelectOneRadio();
        AjaxBehavior valueChangeAction = (AjaxBehavior)FacesUtils.getApplication().createBehavior(AjaxBehavior.BEHAVIOR_ID);

        valueChangeAction.addAjaxBehaviorListener(new ProbeQuestionListener(currentQuestion, "probeDiv" + questionNumber));


        selectUI.addClientBehavior("change", valueChangeAction);
        valueChangeAction.setRender(Collections.singletonList("probeDiv" + questionNumber));

       // further code to customise the control, create the panel group and probe div and wire everything together omitted
    }

这渲染正确,我看到了:

<input type="radio" onchange="mojarra.ab(this,event,'change',0,'probeDiv2')" value="0" id="answer_1:0" name="answer_1">

但是,单击单选按钮会给我一个 javascript 控制台错误:reference error: mojarra is not defined

现在,如果我修改 xhtml 以包含“普通”ajax 控件,例如

<ui:composition xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:p="http://xmlns.jcp.org/jsf/passthrough">

    <h:panelGroup id="id_Group1" binding="#{questionaire.group1}" layout="block"/>

    <!-- include a hacky hidden ajax field to force inclusion of the ajax javascript -->
    <h:panelGroup layout="block" id="hiddenAjaxDiv" style="display:none">
        <h:inputText id="hiddenAjax">
            <f:ajax execute="hiddenAjax" render="hiddenAjaxDiv" />
        </h:inputText>
    </h:panelGroup>    

</ui:composition>

这有效,firebug 网络监视器显示我的 ajax 事件从单选按钮发布到应用程序。

所以,最后,我的问题:

我如何以编程方式强制包含 ajax javascript 库并省去我目前使用的可怕 hack?

注意:我对任何以“不要使用动态生成的组件”开头的答案都不感兴趣 - 出于多种原因,这不是一个选项。

【问题讨论】:

    标签: ajax jsf jsf-2


    【解决方案1】:

    基本上,你需要这个:

    <h:outputScript library="javax.faces" name="jsf.js" target="head" />
    

    该脚本在包含 JSF ajax 脚本的标准 jsf 命名空间中包含 mojarra 定义。

    您可以在主模板的&lt;h:head&gt; 中显式声明它,如有必要,可通过&lt;ui:define&gt;/&lt;ui:include&gt; 进行声明。如果视图已经隐式需要,它不会加载 jsf.js 文件的重复副本。

    您甚至可以通过编程方式创建它:

    UIComponent jsfjs = new UIOutput();
    jsfjs.getAttributes().put("library", "javax.faces");
    jsfjs.getAttributes().put("name", "jsf.js");
    jsfjs.setRendererType("javax.faces.resource.Script");
    FacesContext context = FacesContext.getCurrentInstance();
    context.getViewRoot().addComponentResource(context, jsfjs, "head");
    

    同样,如果视图已经隐式需要,它不会加载 jsf.js 文件的重复副本。


    与具体问题无关,当您需要以编程方式填充组件树时,您应该首选&lt;f:event type="postAddToView"&gt; 而不是binding

    <h:panelGroup id="id_Group1" layout="block">
        <f:event type="postAddToView" listener="#{questionaire.populateGroup1}" />
    </h:panelGroup>
    

    public void populateGroup1(ComponentSystemEvent event) {
        HtmlPanelGorup group1 = (HtmlPanelGroup) event.getComponent();
        // ...
    }
    

    这保证了树在正确的时刻被填充,并使 getter 不受业务逻辑的影响,并避免#{questionaire} 的范围比请求范围更广时潜在的“组件 ID 重复”问题,并保持没有UIComponent 属性的bean,当组件作为可序列化bean 的属性保存时,这反过来又避免了潜在的序列化问题和内存泄漏。

    【讨论】:

    • 太棒了!再一次,你解决了我们的问题。我也会按照您的建议查看 postAddToView。
    • balus,如果我的 bean 在视图范围内,您能否详细说明重复的 ID 问题?我依稀记得不久前在某个地方读过这篇文章,但找不到你讨论它细节的问题
    • @SteveAtkinson 我想现在回复你为时已晚,但如果其他人在这里结束,这里是详细的解释:stackoverflow.com/a/14917453/4170582
    • 感谢您的提示-实际上我忘记了查看-并且提醒很及时,因为我很快需要修改该 bean 以获得一些新功能。这篇文章解释了我在第一次编写我不完全理解的类时看到的一些行为,为了解决它,我可耻地以编程方式重新创建每个请求的视图 - 现在我知道为什么会发生这种情况并且可以改变正确的方法Balus 建议,
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 1970-01-01
    • 2011-06-23
    • 2014-12-18
    • 2016-11-07
    相关资源
    最近更新 更多