3

我正忙于编写自己的 JSF2UIComponent及其相关的渲染器。我所有UIComponent的工具ClientBehaviorHolder。我不明白的是如何真正渲染ClientBehaviorHolder.

例如,以下代码说明了如何ClientBehaviorHolder在 Mojarra 中呈现。

private static void renderHandler(FacesContext context,
                                  UIComponent component,
                                  Collection<ClientBehaviorContext.Parameter> params,
                                  String handlerName,
                                  Object handlerValue,
                                  String behaviorEventName,
                                  String submitTarget,
                                  boolean needsSubmit,
                                  boolean includeExec)
    throws IOException {

    ResponseWriter writer = context.getResponseWriter();
    String userHandler = getNonEmptyUserHandler(handlerValue);
    List<ClientBehavior> behaviors = getClientBehaviors(component, behaviorEventName);

    // Don't render behavior scripts if component is disabled
    if ((null != behaviors) && 
        (behaviors.size() > 0) && 
         Util.componentIsDisabled(component)) {
        behaviors = null;
    }

    if (params == null) {
        params = Collections.emptyList();
    }
    String handler = null;
    switch (getHandlerType(behaviors, params, userHandler, needsSubmit, includeExec)) {

        case USER_HANDLER_ONLY:
            handler = userHandler;
            break;

        case SINGLE_BEHAVIOR_ONLY:
            handler = getSingleBehaviorHandler(context, 
                                               component,
                                               behaviors.get(0),
                                               params,
                                               behaviorEventName,
                                               submitTarget,
                                               needsSubmit);
            break;

        case SUBMIT_ONLY:
            handler = getSubmitHandler(context, 
                                       component,
                                       params,
                                       submitTarget,
                                       true);
            break;

        case CHAIN:
            handler = getChainedHandler(context,
                                        component,
                                        behaviors,
                                        params,
                                        behaviorEventName,
                                        userHandler,
                                        submitTarget,
                                        needsSubmit);
            break;
        default:
            assert(false);
    }


    writer.writeAttribute(handlerName, handler, null);
}

对于提交处理程序,Mojarra 添加了mojarra.jsfcljsjavascript、UIParameters 和其他脚本。对于链处理程序,jsf.util.chain使用。

我的问题是:

  • 如何确定我们是否必须在链中呈现处理程序或单个行为或用户特定的处理程序?
  • mojarra.jsfcljs只有莫哈拉独有。PrimeFaces 有自己的实现,Apache Tomahawk 也有。问题是:它mojarra.jsfcljs的作用是什么,它的用途是什么?这样我就可以自己写一篇了?另外,我在哪里可以找到的实现mojarra.jsfcljs
  • 要渲染的规范是什么ClientBehaviorHolder

提前致以诚挚的感谢。

4

1 回答 1

5

如何确定我们是否必须在链中呈现处理程序或单个行为或用户特定的处理程序?

想象一下最终用户(阅读:使用您的组件的 JSF 开发人员)编写了:

<your:component onclick="return foo()" />

你打算最终为你的组件自己的目的进行渲染:

<someHtmlElement onclick="jsf.ajax.request(...); return false;" />

然后你不能像这样onclick在你的组件前面连接最终用户jsf.ajax.request()

<someHtmlElement onclick="return foo(); jsf.ajax.request(...); return false;" />

即使它返回了true,你的组件jsf.ajax.request也不会被调用。您最终希望得到如下结果:

<someHtmlElement onclick="if returnsTrue('return foo();') { jsf.ajax.request(...); } return false;" />

这正是幕后jsf.util.chain()所做的。


mojarra.jsfcljs只有莫哈拉独有。PrimeFaces 有自己的实现,Apache Tomahawk 也有。问题是:它mojarra.jsfcljs的作用是什么,它的用途是什么?这样我就可以自己写一篇了?另外,我在哪里可以找到的实现mojarra.jsfcljs

它在jsf.js文件里面。找到它的简单方法是打开一个<f:ajax>嵌入的 JSF 页面,并在生成的<head>源代码中查找<script>它的 URL。默认情况下,此文件已缩小。如果您将javax.faces.PROJECT_STAGEcontext 参数设置为Development,那么这将是未缩小的。该jsfcljs()函数的任务是提交带有必要参数的父表单。这是来自 Mojarra 2.1.21 的相关性摘录。

/*
 * This is called by command link and command button.  It provides
 * the form it is nested in, the parameters that need to be
 * added and finally, the target of the action.  This function
 * will delete any parameters added <em>after</em> the form
 * has been submitted to handle DOM caching issues.
 *
 * @param f - the target form
 * @param pvp - associative array of parameter
 *  key/value pairs to be added to the form as hidden input
 *  fields.
 * @param t - the target of the form submission
 */
mojarra.jsfcljs = function jsfcljs(f, pvp, t) {

要渲染的规范是什么ClientBehaviorHolder

用于ClientBehavior#getScript()获取自动生成的脚本。它需要一个ClientBehaviorContext可以使用创建的参数ClientBehaviorContext#createClientBehaviorContext()。反过来,您有责任将其呈现为适当的 HTML 属性,例如onclick.

FacesContext context = FacesContext.getCurrentInstance();
UIComponent inputOrCommandComponent = ...; // Your component.
String event = "click"; // Just the particular HTML DOM event name you need to listen on.

ClientBehaviorContext clientBehaviorContext = ClientBehaviorContext.createClientBehaviorContext(context, component, event, component.getClientId(context), null);
StringBuilder builder = new StringBuilder();

for (ClientBehavior behavior : component.getClientBehaviors().get(event)) { // Collect all <f:ajax> declarations on the given event.
    builder.append(behavior.getScript(clientBehaviorContext));
    builder.append(';');
}

String script = builder.toString();
// Write it to the desired HTML attribute.

请注意,您绝对不必担心以这种方式编写特定于 JSF 实现的脚本。它们将为您生成。

总而言之,ClientBehaviorHolder只是对 ajax 支持的抽象。它允许开发人员嵌套<f:ajax>在您的组件中。所有标准的 JSFUIInputUICommand组件都实现了它。

于 2013-06-29T19:54:37.783 回答