渲染ClientBehaviorHolder

Buh*_*ndi 3 ajax renderer custom-component jsf-2

我正在忙着编写自己的JSF2 UIComponent及其相关的渲染器.我所有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);
}
Run Code Online (Sandbox Code Playgroud)

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

我的问题是:

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

我真诚地感谢你们.

Bal*_*usC 5

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

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

<your:component onclick="return foo()" />
Run Code Online (Sandbox Code Playgroud)

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

<someHtmlElement onclick="jsf.ajax.request(...); return false;" />
Run Code Online (Sandbox Code Playgroud)

那么你不能只是onclick在你的组件前面连接最终用户jsf.ajax.request()就像这样

<someHtmlElement onclick="return foo(); jsf.ajax.request(...); return false;" />
Run Code Online (Sandbox Code Playgroud)

即使它返回true,jsf.ajax.request也不会调用您的组件.你最终想要结束这样的事情:

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

这正是jsf.util.chain()在幕后做的事情.


mojarra.jsfcljs只有Mojarra才有.PrimeFaces有自己的实现,Apache Tomahawk也是如此.问题是:mojarra.jsfcljs它的用途和用途是什么?这样我可以为自己写一个?另外,我在哪里可以找到执行mojarra.jsfcljs

它在jsf.js文件中.找到它的简单方法是打开一个<f:ajax>嵌入的JSF页面,并查看生成的<head>源代码<script>及其URL.默认情况下,此文件已缩小.如果您将javax.faces.PROJECT_STAGE上下文参数设置为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) {
Run Code Online (Sandbox Code Playgroud)

要呈现的规范是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.
Run Code Online (Sandbox Code Playgroud)

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

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