JSF 自定义组件:如何获取 <f:ajax /> 的属性

Posted

技术标签:

【中文标题】JSF 自定义组件:如何获取 <f:ajax /> 的属性【英文标题】:JSF Custom Component: How to get attribute of <f:ajax /> 【发布时间】:2011-11-08 06:05:15 【问题描述】:

我已经为 jsf 编写了一个自定义组件。渲染器扩展了 com.sun.faces.renderkit.html_basic.ListboxRenderer。我的组件在“javax.faces.SelectMany”-Family 中。

jsf-page中的代码如下:

<tb:myMenu id="testId" value="#valueForm.someValue">  
    <f:selectItem /> 
    <f:selectItems value="#dao.getSomething()"  />
    <f:ajax render=":myTestForm:myId"/>
</tb:myMenu>

如何在我的渲染器中获取渲染属性的值?我只需要值,不应该向我的组件写入任何内容(就像 RenderKitUtils-class 那样)

我目前的解决方案如下所示。它有效,但我对此并不满意。

if (component instanceof ClientBehaviorHolder) 
        Map<String, List<ClientBehavior>> behaviors = ((ClientBehaviorHolder)component).getClientBehaviors();
        if (behaviors != null && behaviors.keySet().contains("valueChange")) 
            for (ClientBehavior cb: behaviors.get("valueChange")) 
                if (cb instanceof AjaxBehavior) 
                    System.out.println("AJAX: " + ((AjaxBehavior) cb).getRender());
                
            
        
    

【问题讨论】:

【参考方案1】:

你到底有多不开心?太冗长了?好吧,JSF API 和 Mojarra impl 确实没有提供任何实用方法来隐藏它。它只是停在这里。你必须自己写。

至少,在你的 sn-p 中,第二个if 检查null 是多余的,因为它never 返回null。此外,同一行上的behaviors.keySet().contains(key) 也可以简化为behaviors.containsKey(key)。鉴于它永远不会返回 null,您也可以立即获取行为列表并对其进行空检查。

最后用一些实用方法隐藏它。

public static Set<String> getClientBehaviorRenderIds(UIComponent component, String behaviorName) 
    Set<String> clientBehaviorRenderIds = new HashSet<String>();

    if (component instanceof ClientBehaviorHolder) 
        List<ClientBehavior> clientBehaviors = ((ClientBehaviorHolder) component).getClientBehaviors().get(behaviorName);

        if (clientBehaviors != null) 
            for (ClientBehavior clientBehavior : clientBehaviors) 
                if (clientBehavior instanceof AjaxBehavior) 
                    clientBehaviorRenderIds.addAll(((AjaxBehavior) clientBehavior).getRender());
                
            
        
    

    return clientBehaviorRenderIds;

以便您可以按如下方式使用它:

Set<String> renderIds = getClientBehaviorRenderIds(component, "valueChange");
// ...

如果是嵌套检查令人不安,您也可以进行反向检查(Mojarra 一般也是这样写的;深度if 嵌套确实是一种不好的做法):

public static Set<String> getClientBehaviorRenderIds(UIComponent component, String behaviorName) 
    Set<String> clientBehaviorRenderIds = new HashSet<String>();

    if (!(component instanceof ClientBehaviorHolder)) 
        return clientBehaviorRenderIds;
    

    List<ClientBehavior> clientBehaviors = ((ClientBehaviorHolder) component).getClientBehaviors().get(behaviorName);

    if (clientBehaviors == null) 
        return clientBehaviorRenderIds;
    

    for (ClientBehavior clientBehavior : clientBehaviors) 
        if (clientBehavior instanceof AjaxBehavior) 
            clientBehaviorRenderIds.addAll(((AjaxBehavior) clientBehavior).getRender());
        
    

    return clientBehaviorRenderIds;

【讨论】:

好的,我认为可能有一个实用方法,但我没有看到。感谢您的逆向检查;)

以上是关于JSF 自定义组件:如何获取 <f:ajax /> 的属性的主要内容,如果未能解决你的问题,请参考以下文章

JSF 2 - 如何将 Ajax 侦听器方法添加到复合组件接口?

JSF 2——在 f:ajax 上具有可选监听器属性的复合组件

jsf ajax 部分渲染

发出 JSF Ajax 请求时显示加载进度

JSF / PrimeFaces - 如何显示自定义验证器的消息,但不显示同一组件上的必需验证

使用 f:ajax 时 JSF 不触发 bean setter