Thursday 5 July 2012

ADF client behavior in iterator or table

Following the post about how to create client behaviors I have another tip. Suppose you need to put behavior inside an iterator or a table and you need to evaluate it for each row, like is:
<af:iterator var="row" value="...">
    <af:outputText value="...">
        <ca:customBehavior value="#{row.val}"
    </af:outputText>
</af:iterator>
In this situation the implementation method described in mentioned above post will not work.
Actually, if you look at the implementation of class BehaviorTag you will see that there exists another way to define behavior: through getBehaviorExpression(ELContext) method. Here is a snippet from BehaviorTag:
...
ValueExpression behaviorExpression = getBehaviorExpression(component);
if (behaviorExpression != null) {
    cls.addBehavior(behaviorExpression);
} else {
    String behavior = getBehavior(component);
    if (behavior != null) {
    cls.addBehavior(behavior);
}
...
First, it tries getBehaviorsExpression method and if the method returns null it calls getBehavior.
Notice, that getBehaviorExpression returns a ValueExpression object.
Now, if we want our behavior to be properly evaluated we have to implement getBehaviorExpression, and the suggested way to do this is by providing implementation of ValueExpressionBase class:
@Override
protected ValueExpression getBehaviorExpression(UIComponent uIComponent) {
    return new CustomBehaviorVE(value);
}

private static class CustomBehaviorVE extends ValueExpressionBase {

    private ValueExpression value;
    
    public CustomBehaviorVE(ValueExpression value) {
        super();
        this.value = value;
    }

    public Object getValue(ELContext elContext) {
        String val = value == null ? "" : 
            ComponentUtils.resolveString(value.getValue(elContext));
        return "new CuCustomBehavior('" + val + "')";
    }
}
In the method getValue of our ValueExpression we, basically, do the same we've done in getBehavior method before. Except that expression evaluation context ELContext is provided by method argument.
That's it. Now your behavior will properly work in an iterator, and it will be added to every client object (though there is still only one instance of Behavior's class on server).

No comments:

Post a Comment