以编程方式添加Ajax行为-“未定义Mojarra"; [英] Programatically adding Ajax Behaviour - "Mojarra is not defined"

查看:96
本文介绍了以编程方式添加Ajax行为-“未定义Mojarra";的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用动态表单的页面,在该页面上以编程方式创建了组件树(这个问题不值得讨论),我需要呈现的某些输入控件需要ajax处理程序.

I have a page using dynamic forms where I am creating the component tree programatically (which is not up for debate in this question) Some of the input controls I need to render require an ajax handler.

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

The xhtml fragment (included by a <ui:include> from another fragment) is :

<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答案,我有以下bean代码:

Based on other SO anwsers, I have the following bean code:

   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
    }

这可以正确渲染,我看到了:

This renders correctly and I see:

<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

However, clicking the radio button gives me a javascript console error: reference error: mojarra is not defined

现在,如果我将xhtml修改为包括正常" ajax控件,例如

Now, if I modify the xhtml to include a "normal" ajax control, e.g.

<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事件已发布到应用程序.

This works and firebug network monitor shows my ajax event from the radio button is posted to the app.

所以,最后,我的问题:

So, finally, my question:

我如何以编程方式强制包含ajax javascript库并免除我当前正在使用的可怕骇客?

How do I programatically force the inclusion of the ajax javascript library and dispense with the horrible hack I am currently using?

注意:我对以不要使用动态生成的组件"开头的任何答案都不感兴趣-由于多种原因,这不是一种选择.

推荐答案

基本上,您需要这样做:

Basically, you need this:

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

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

That script contains the mojarra definition among the standard jsf namespace containing the JSF ajax scripts.

您可以在主模板的<h:head>中明确声明它,如有必要,可以通过<ui:define>/<ui:include>进行声明.如果视图已隐式要求,它将不会加载jsf.js文件的重复副本.

You can explicitly declare it in the <h:head> of your master template, if necessary via <ui:define>/<ui:include>. It won't load duplicate copies of the jsf.js file if already implicitly required by the view.

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

You can even programmatically create it:

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文件的重复副本.

Also here, it won't load duplicate copies of the jsf.js file if already implicitly required by the view.

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

Unrelated to the concrete problem, you should prefer <f:event type="postAddToView"> over binding when you need to programmatically populate the component tree:

<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();
    // ...
}

这保证了在正确的时机填充树,并使获取器摆脱业务逻辑,并避免了#{questionaire}的范围比请求范围大时潜在的重复组件ID"麻烦,并保持了bean没有UIComponent属性,当组件作为可序列化bean的属性保存时,这反过来避免了潜在的序列化麻烦和内存泄漏.

This guarantees that the tree is populated at exactly the right moment, and keeps getters free of business logic, and avoids potential "duplicate component ID" trouble when #{questionaire} is in a broader scope than the request scope, and keeps the bean free of UIComponent properties which in turn avoids potential serialization trouble and memory leaking when the component is held as a property of a serializable bean.

这篇关于以编程方式添加Ajax行为-“未定义Mojarra";的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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