0

I've been studying how to develop JSF custom components to improve my knowledge about how it works (it's been quite interesting so far).

I made my own commandButton (extended from HtmlCommandButton) and it worked as expected when doing all decoding and enconding in the component class.

When I decided to create a separated faces renderer for my component it stopped working. After some research I learned that I had to override the decode method of my renderer and it was working before just because this method was already implemented by HtmlCommandButton.

After some research I found out how to decode action listeners (thanks to BalusC) and I also learnt how to decode ajax events. However I still didn't know how to decode actions.

This is my decode method right now:

@Override
public void decode(FacesContext context, UIComponent component) {
    CommandButtonUI commandButton = (CommandButtonUI) component;
    //decode click ajax events
    List<ClientBehavior> clientBehaviours = commandButton.getClientBehaviors().get("click");
    if (clientBehaviours != null) {
        for (ClientBehavior cb : clientBehaviours) {
            cb.decode(context, component);
        }
    }
    //decode action listenet
    if (context.getExternalContext().getRequestParameterMap().containsKey(commandButton.getClientId(context))) {
        component.queueEvent(new ActionEvent(component));
    }
}

I already tried to find HtmlCommandButton's decode source and analyse it, but I failed to find it, since apparently it's generated by a plugin.

Community
  • 1
  • 1

1 Answers1

0

This is how i do it. But don't got forget: 1) to add the @FacesRenderer annotation to your render class with the respective componentFamily and rendererType values. 2) to define your component RenderType on your component class using setRendererType in the class constructor.

public void decode(FacesContext pContext, UIComponent pComponent) {
    YourComponent xButton = (DBSButton) pComponent;         
    String        xClientId = xButton.getClientId(); 
    if(xButton.getReadOnly()) {return;}

    decodeBehaviors(pContext, xButton);

    if (RenderKitUtils.isPartialOrBehaviorAction(pContext, xClientId)    
     || pContext.getExternalContext().getRequestParameterMap().containsKey(xClientId)) {
        xButton.queueEvent(new ActionEvent(xButton));    
    }
}

protected void decodeBehaviors(FacesContext pContext, UIComponent pComponent)
{
    if(!(pComponent instanceof ClientBehaviorHolder)) {
        return;
    }

    Map<String, List<ClientBehavior>> xBehaviors = ((ClientBehaviorHolder) pComponent).getClientBehaviors();
    if(xBehaviors.isEmpty()) {
        return;
    }

    Map<String, String> xParams = pContext.getExternalContext().getRequestParameterMap();
    String xBehaviorEvent = xParams.get("javax.faces.behavior.event");

    if(null != xBehaviorEvent) {
        List<ClientBehavior> xBehaviorsForEvent = xBehaviors.get(xBehaviorEvent);

        if(xBehaviorsForEvent != null && !xBehaviorsForEvent.isEmpty()) {
           String xBehaviorSource = xParams.get("javax.faces.source");
           String xClientId = pComponent.getClientId();

           if(xBehaviorSource != null && xClientId.startsWith(xBehaviorSource)) {
               for(ClientBehavior xBehavior: xBehaviorsForEvent) {
                   xBehavior.decode(pContext, pComponent);
               }
           }
        }
    }
}
rvillar
  • 76
  • 5
  • I'm stil trying to understand it (it seems it just follows step-by-step what's specified in the renderkit documentation for the decode behaviour), but it worked for me. Thanks. ^^ – Humberto Ferreira Da Luz Nov 29 '15 at 13:49