Details
-
Improvement
-
Status: Closed
-
Major
-
Resolution: Fixed
-
2.3.9
-
None
Description
We're trying to implement a few JSF components that extend from the generic JSF components/renderers. This particular component is extending javax.faces.component.html.HtmlInputText.
On the renderer side, we're grabbing a handle to the default renderer of the component:
private static final String PARENT_FAMILY = "javax.faces.Input"; private static final String PARENT_RENDERER = "javax.faces.Text"; static final Renderer getWrappedRenderer(FacesContext context) { Renderer baseRenderer = context.getRenderKit().getRenderer(PARENT_FAMILY, PARENT_RENDERER); return baseRenderer; }
Then we're going to attempt to write out some new CSS classes for the component and leave the rest of everything alone:
@Override public void encodeBegin(FacesContext context, UIComponent component) throws IOException { Renderer baseRenderer = getWrappedRenderer(context); baseRenderer.encodeBegin(context, component); XXFaces.writeClasses(context, null, SF_FORM_CONTROL, BS_FORM_CONTROL); } @Override public void encodeEnd(FacesContext context, UIComponent component) throws IOException { Renderer baseRenderer = getWrappedRenderer(context); baseRenderer.encodeEnd(context, component); }
This unfortuantely presents a problem. HtmlTextRendererBase does not have an encodeBegin() method, instead it does all of the "Start tag" encoding in the encodeEnd() method. This makes it impossible to create custom components that wrap the functionality of the default render kit without extending myfaces renderers and breaks any chance cross-platform components.
I propose adding this method to HtmlTextRendererBase:
@Override public void encodeBegin(FacesContext context, UIComponent component) throws IOException { if (component instanceof UIInput) { renderInputBegin(context, component); } }
and changing encodeEnd() to this following:
public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException { org.apache.myfaces.shared.renderkit.RendererUtils.checkParamValidity(facesContext,component,null); Map<String, List<ClientBehavior>> behaviors = null; if (component instanceof ClientBehaviorHolder) { behaviors = ((ClientBehaviorHolder) component).getClientBehaviors(); if (!behaviors.isEmpty()) { ResourceUtils.renderDefaultJsfJsInlineIfNecessary(facesContext, facesContext.getResponseWriter()); } } if (component instanceof UIInput) { renderInputEnd(facesContext, component); } else if (component instanceof UIOutput) { renderOutput(facesContext, component); } else { throw new IllegalArgumentException("Unsupported component class " + component.getClass().getName()); } }
This changes this section of encodeEnd()
if (component instanceof UIInput) { renderInput(facesContext, component); }
And removes the renderInput() method which just calls renderInputBegin() followed by renderInputEnd() anyway.
I'm open to ideas an improvements. And one more note, open source work often goes unthanked, and I would like to express my gratitude for your work and passion on the MyFaces project at the ASF.