Rules for checking rendered-attribute for JSF2 custom-component

829 views Asked by At

I have a simple custom-component like this which does not respect the attribute rendered.

@FacesComponent("my.OutputText")
public class OutputText extends UIPanel
{   
  @Override public void encodeBegin(FacesContext context) throws IOException {...}
  @Override public void encodeEnd(FacesContext context) throws IOException {...}
}

Of course, I can check for the attribute rendered in both methods, add @Override public boolean getRendersChildren() and also check for the rendered attribute and then simple not render the children in encodeChildren.

But what is the recommended rule for implementing this common feature?

1

There are 1 answers

0
BalusC On

That's already described in javadoc of UIComponent class.

To take encodeBegin() method as an example:

encodeBegin

public abstract void encodeBegin(FacesContext context)
                     throws java.io.IOException

If our rendered property is true, render the beginning of the current state of this UIComponent to the response contained in the specified FacesContext. Call pushComponentToEL(javax.faces.context.FacesContext,javax.faces.component.UIComponent). Call Application.publishEvent(javax.faces.context.FacesContext, java.lang.Class, java.lang.Object), passing PreRenderComponentEvent.class as the first argument and the component instance to be rendered as the second argument.

If a Renderer is associated with this UIComponent, the actual encoding will be delegated to Renderer#encodeBegin(FacesContext, UIComponent).

If our rendered property is false, call pushComponentToEL(javax.faces.context.FacesContext,javax.faces.component.UIComponent) and return immediately.

And getRendersChildren() method:

getRendersChildren

public abstract boolean getRendersChildren()

Return a flag indicating whether this component is responsible for rendering its child components. The default implementation in UIComponentBase#getRendersChildren tries to find the renderer for this component. If it does, it calls Renderer#getRendersChildren and returns the result. If it doesn't, it returns false. As of version 1.2 of the JavaServer Faces Specification, component authors are encouraged to return true from this method and rely on UIComponentBase#encodeChildren.

Note the last statement. Here's the one for UIComponent#encodeChildren():

encodeChildren

public abstract void encodeChildren(FacesContext context)
                         throws java.io.IOException

If our rendered property is true, render the child UIComponents of this UIComponent. This method will only be called if the rendersChildren property is true.

If a Renderer is associated with this UIComponent, the actual encoding will be delegated to Renderer#encodeChildren(FacesContext, UIComponent). If no Renderer is associated with this UIComponent, iterate over each of the children of this component and call encodeAll(javax.faces.context.FacesContext).

Note that UIComponentBase has them already implemented. If you have overridden a method, then you'd need to follow exactly the same rules or perhaps make use of super.encodeXxx() if possible. If you don't have encodeChildren() overridden, then you don't need to do so anyway.