[jsr-314-open-mirror] [jsr-314-open] Use a Renderer on a composite component

Leonardo Uribe lu4242 at gmail.com
Mon Mar 29 12:12:48 EDT 2010


2010/3/29 Ed Burns <edward.burns at oracle.com>

> >>>>> On Sun, 28 Mar 2010 21:21:10 -0500, Leonardo Uribe <lu4242 at gmail.com>
> said:
>
> LU> The problem is why it is mandatory to set "javax.faces.Composite" as
> LU> renderer type. The javadoc should say:
>
> LU> "...If the renderer type is not set (return null), Call
> LU>
> UIComponent.setRendererType(java.lang.String)<file:///D:/jdk-1_5_0-doc/jsf20/mojarra-2.0.3-SNAPSHOT/docs/javadocs/javax/faces/component/UIComponent.html#setRendererType%28java.lang.String%29>on
> LU> the
> LU> UIComponent instance, passing "javax.faces.Composite" as the
> argument...".
> LU> In that case, a user can override the rendererType on the constructor
> and
> LU> avoid this hack that works with the current spec:
>
> I understand the problem you have uncovered.  Take a look at the
> renderkit docs for javax.faces.NamingContainer/javax.faces.Composite.
> There are specific requirements in there that depend on the composite
> component metadata specification.
>
> I thought it would be toooooooo subtle to allow the Renderer to be
> customized beause this contract must also be followed in the custom
> renderer case.
>
> LU> Why override the default Renderer and use a custom one? Let's
> LU> suppose the component proposed needs some custom code for converter,
> LU> or for decode. The right place to put that kind of code is the
> LU> Renderer class, not the component, but note it is possible to put
> LU> that on the component class.
>
> Yes I understand that the Renderer is the right place for such things
> but the chosen programming model for customization of composite
> components is to override the top level component.  Simple.  If we're
> going to change that I need a more compelling reason than correctness.
>
>
The current behavior of javax.faces.NamingContainer/javax.faces.Composite
renderer says that everything
inside the facet UIComponent.COMPOSITE_FACET_NAME should be rendered. But
sometimes
the markup of the component changes according to its inner state. One simple
example is
h:commandLink. If this component is disabled, it should be rendered a <span>
instead use <a>.
Other example is tomahawk displayValueOnly property, that when is set to
true, only the value
needs to be rendered.

Ok, if I have a composite component the first thought is use c:if tag, but
remember that with
partial state saving enabled this tag is evaluated when the view is build,
not when it is
rendered. Other alternative is use a component that allows to render one
child at the time, and
it is on myfaces commons (mc:renderOne, old sandbox s:limitRendered). The
third alternative is
use a custom renderer. The example I'm trying to do is this (all non
relevant code has been removed:

    public void encodeEnd(FacesContext context, UIComponent component)
            throws IOException
    {
        UIComponent compositeFacet = (UIComponent) component
                .getFacet(UIComponent.COMPOSITE_FACET_NAME);
        CompositeInputHtml editor = (CompositeInputHtml) component;
        if( HtmlRendererUtils.isDisplayValueOnly(editor) )
        {
            encodeDisplayValueOnly(context, editor);
        }
        else if ( useFallback(editor) )
        {
            encodeEndFallBackMode(context, editor);
        }
        else
        {
            if( ! isVisible(editor) ){
                encodeHidden(context, editor);
            }
            else if( ! hasAnotherPropertyThatPreventsRenderThisOneCorrectly(
context ) )
            {
                compositeFacet.encodeAll(context);
            }
            else
            {
                encodeEndFallBackMode(context, editor);
            }
        }
    }

It is possible to think in other cases, like a composite component like
this:

<composite:implementation>
<f:facet name="normal">
......some html markup......
</f:facet>
<f:facet name="disabled">
......some html markup......
</f:facet>
<f:facet name="special">
......some html markup......
</f:facet>
<composite:implementation>

And use a custom renderer to control when one or other facet should be
rendered.

Note that in fact, with the hack on the component class on setRendererType,
it is possible
to override the Renderer without problem, so for my particular problem I can
live with it.
The question is if the spec should enforce the use of
javax.faces.NamingContainer/javax.faces.Composite renderer for composite
components
or not.

Leonardo


> Ed
>
> --
> | edward.burns at oracle.com  | office: 408 884 9519 OR x31640
> | homepage:                | http://ridingthecrest.com/
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.jboss.org/pipermail/jsr-314-open-mirror/attachments/20100329/f800e573/attachment-0002.html 


More information about the jsr-314-open-mirror mailing list