webtier@glassfish.java.net

Re: Custom component with AjaxBehavior

From: <webtier_at_javadesktop.org>
Date: Wed, 23 Sep 2009 10:38:10 PDT

Hopefully you can see this, as the forum seems a bit broken right now.

You have several errors in your code, some trivial (using getId instead of getClientId, as well as leaving out the name attribute), and some really serious (missing decode section). Not surprising, since, as you note, there isn't an example to follow.

Here's some working code - I'll blog this up later. (Also, note that what you want to do in *this* example is probably better done in a composite component.)

@FacesComponent(value = "mycustom")
public class MyCustom extends UIComponentBase implements ClientBehaviorHolder {

    @Override
    public String getFamily() {
        return "custom";
    }

    @Override
    public void encodeEnd(FacesContext context) throws IOException {

        ClientBehaviorContext behaviorContext =
                ClientBehaviorContext.createClientBehaviorContext(context,
                this, "click", getClientId(context), null);

        ResponseWriter responseWriter = context.getResponseWriter();
        responseWriter.startElement("div", null);
        responseWriter.writeAttribute("id",getClientId(context),"id");
        responseWriter.writeAttribute("name", getClientId(context),"clientId");
        Map<String,List<ClientBehavior>> behaviors = getClientBehaviors();
        if (behaviors.containsKey("click") ) {
            String click = behaviors.get("click").get(0).getScript(behaviorContext);
            responseWriter.writeAttribute("onclick", click, null);
        }
        responseWriter.write("Yo! Click me already!");
        responseWriter.endElement("div");
    }

    
    @Override
    public void decode(FacesContext context) {
        Map<String, List<ClientBehavior>> behaviors = getClientBehaviors();
        if (behaviors.isEmpty()) {
            return;
        }

        ExternalContext external = context.getExternalContext();
        Map<String, String> params = external.getRequestParameterMap();
        String behaviorEvent = params.get("javax.faces.behavior.event");

        if (behaviorEvent != null) {
            List<ClientBehavior> behaviorsForEvent = behaviors.get(behaviorEvent);

            if (behaviors.size() > 0) {
                String behaviorSource = params.get("javax.faces.source");
               String clientId = getClientId(context);
               if (null != behaviorSource && behaviorSource.equals(clientId)) {
                   for (ClientBehavior behavior: behaviorsForEvent) {
                       behavior.decode(context, this);
                   }
               }
            }
        }
    }

    @Override
    public Collection<String> getEventNames() {
        return Arrays.asList("click");
    }

    @Override
    public String getDefaultEventName() {
        return "click";
    }
}


Since "click" is now the default, you can just do something like:

<cu:custom id="customId">
                <f:ajax render="eventcount" listener="#{custom.updateEventCount}"/>
</cu:custom>
[Message sent by forum member 'driscoll' (jim.driscoll_at_sun.com)]

http://forums.java.net/jive/thread.jspa?messageID=365336