简体   繁体   中英

JSF Custom Component: How to get attribute of <f:ajax />

I have written a custom component for jsf. The renderer extends com.sun.faces.renderkit.html_basic.ListboxRenderer. My component is in "javax.faces.SelectMany"-Family.

The code in jsf-page looks like this:

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

How can i get the value of the render-attribute in my Renderer? I only need the value, there should nothing be written to my component (like RenderKitUtils-class does)

My current solution is shown below. It works, but i am not happy about it.

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

How exactly are you not happy about it? Too verbose? Well, there's indeed no utility method provided by JSF API nor by Mojarra impl which hides that away. It just stops here. You've to write it yourself.

At least, in your snippet the 2nd if check on null is superfluous, because it never returns null . Further the behaviors.keySet().contains(key) on the same line can also be simplified to behaviors.containsKey(key) . Given the fact that it never returns null , you could also just get the list of behaviors immediately and nullcheck it instead.

Finally just hide it away in some utility method.

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;
}

so that you can use it as follows:

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

If it are the nested checks which is disturbing, you can also do the inverse checks (this is also how Mojarra is written in general; deep if nesting is indeed a poor practice):

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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM