[ 
https://issues.apache.org/jira/browse/MYFACES-4430?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Melloware resolved MYFACES-4430.
--------------------------------
    Resolution: Fixed

PR merged

> Separate "begin tag" code from "end tag" code for HtmlCheckboxRendererBase
> --------------------------------------------------------------------------
>
>                 Key: MYFACES-4430
>                 URL: https://issues.apache.org/jira/browse/MYFACES-4430
>             Project: MyFaces Core
>          Issue Type: Improvement
>          Components: General
>    Affects Versions: 2.3.9
>            Reporter: glynn leininiger
>            Assignee: Melloware
>            Priority: Major
>             Fix For: 2.3.10, 2.3-next-M7, 3.0.2
>
>
> This ticket is very similar to MYFACES-4428, except it applies to 
> HtmlSelectBooleanCheckbox. 
> 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.HtmlSelectBooleanCheckbox.
> On the renderer side, we're grabbing a handle to the default renderer of the 
> component:
> {code:java}
>       private static final String PARENT_FAMILY = "javax.faces.Checkbox";
>       private static final String PARENT_RENDERER = 
> "javax.faces.SelectBoolean";
>       static final Renderer getWrappedRenderer(FacesContext context) {
>               Renderer baseRenderer = 
> context.getRenderKit().getRenderer(PARENT_FAMILY, PARENT_RENDERER);
>               return baseRenderer;
>       }{code}
> Then we're going to attempt to write out some new CSS classes for the 
> component and leave the rest of everything alone:
> {code:java}
>       @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);
>       } {code}
>  
> The problem is HtmlCheckboxRendererBase 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 in HtmlCheckboxRendererBase:
> {code:java}
>     @Override    
>  public void encodeBegin(FacesContext facesContext, UIComponent uiComponent)
>         throws IOException
> {
>     
> org.apache.myfaces.shared.renderkit.RendererUtils.checkParamValidity(facesContext,
>  uiComponent, null);
>     
>     Map<String, List<ClientBehavior>> behaviors = null;
>     if (uiComponent instanceof ClientBehaviorHolder)
>     {
>         behaviors = ((ClientBehaviorHolder) uiComponent).getClientBehaviors();
>         if (!behaviors.isEmpty())
>         {
>             ResourceUtils.renderDefaultJsfJsInlineIfNecessary(facesContext, 
> facesContext.getResponseWriter());
>         }
>     }
>     
>     if (uiComponent instanceof UISelectBoolean)
>     {
>         Boolean value = 
> org.apache.myfaces.shared.renderkit.RendererUtils.getBooleanValue( 
> uiComponent );
>         boolean isChecked = value != null ? value.booleanValue() : false;
>         renderCheckbox(facesContext, uiComponent, EXTERNAL_TRUE_VALUE, 
> false,isChecked, true, null); 
>             //TODO: the selectBoolean is never disabled
>     }
>     else if (uiComponent instanceof UISelectMany)
>     {
>         // let the current impl do what it does in encodeEnd do nothing here 
> just don't want exception
>         // throw if it is this case
>         log.finest("encodeBegin() doing nothing intentionally for 
> UISelectMany");
>     }
>     else
>     {
>         throw new IllegalArgumentException("Unsupported component class "
>                 + uiComponent.getClass().getName());
>     }
> }{code}
> and changing encodeEnd() to this following:
> {code:keyword}
>     public void encodeEnd(FacesContext facesContext, UIComponent uiComponent) 
> throws IOException
> {
>     if (uiComponent instanceof UISelectBoolean)
>     {
>         ResponseWriter writer = facesContext.getResponseWriter();
>         writer.endElement(HTML.INPUT_ELEM);
>     }
>     else if (uiComponent instanceof UISelectMany)
>     {
>         renderCheckboxList(facesContext, (UISelectMany) uiComponent);
>     }
>     else
>     {
>         throw new IllegalArgumentException("Unsupported component class " + 
> uiComponent.getClass().getName());
>     }
> }{code}
> and add this to the end of renderCheckbox()
> {code:java}
> if (uiComponent instanceof UISelectMany)
> {
>     writer.endElement(HTML.INPUT_ELEM);
> }{code}
> These changes split the logic for encode end and begin for renderCheckbox() 
> and leaves the rendering logic alone for renderCheckboxList(). Encode begin 
> calls renderCheckbox and encodeEnd writes the end element. Encode begin does 
> nothing for UISelectMany elements as it is implemented in encodeEnd.
> Im open to any feedback on this proposed change. 



--
This message was sent by Atlassian Jira
(v8.20.1#820001)

Reply via email to