[
https://issues.apache.org/jira/browse/MYFACES-1493?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12606998#action_12606998
]
K. Ghadami commented on MYFACES-1493:
-------------------------------------
i analized and soleved the Problem.
The renderer trys to use the value in the select items to render the value of
the option tags - which is wrong!
Because the value of the selectitem is not need to be a string. Some people
mean u just need a converter but that is not what the jsf spec says.
So what we need is a renderer that simply use numbers for the value of the
option tag.
If like t share my render with u, that aceppt all all objets in the selectItem
value.
it only testet for selectOneMenu. You can find the current code on my german
blog:
http://art-of-software-engineering.blogspot.com/2008/06/selectonemenu-und-die.html
in the facesconfig i registered my renderer:
<render-kit>
<renderer>
<description>Renderer accepting objekts as value for select itmes</description>
<component-family>javax.faces.SelectOne</component-family>
<renderer-type>javax.faces.Menu</renderer-type>
<renderer-class>jsf.MenuRenderer</renderer-class>
</renderer>
</render-kit>
Here the comes the render. it would be nice if some on could provide a real
patch(svn diff) so the pain will be gone in the next version of myfaces, ;-)
i changed, and mixed up so much code, that i am not quit sure how to provied a
good patch:
package jsf;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import javax.faces.component.UIComponent;
import javax.faces.component.UISelectMany;
import javax.faces.component.UISelectOne;
import javax.faces.component.html.HtmlSelectManyMenu;
import javax.faces.component.html.HtmlSelectOneMenu;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.model.SelectItem;
import javax.faces.model.SelectItemGroup;
import org.apache.myfaces.shared_impl.component.EscapeCapable;
import org.apache.myfaces.shared_impl.renderkit.JSFAttr;
import org.apache.myfaces.shared_impl.renderkit.RendererUtils;
import org.apache.myfaces.shared_impl.renderkit.html.HTML;
import org.apache.myfaces.shared_impl.renderkit.html.HtmlRenderer;
import org.apache.myfaces.shared_impl.renderkit.html.HtmlRendererUtils;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* 14.06.2008 modified by K.Ghadami
* Now accepting non Sting values in selectItems
*/
/**
* X-CHECKED: tlddoc of h:selectManyListbox
*
* @author Manfred Geiler (latest modification by $Author: matzew $)
* @author Thomas Spiegl
* @version $Revision: 597729 $ $Date: 2007-11-23 14:25:55 -0500 (Fri, 23 Nov
* 2007) $
*/
public class MenuRenderer extends HtmlRenderer {
// private static final Log log =
LogFactory.getLog(HtmlMenuRenderer.class);
public void encodeEnd(FacesContext facesContext, UIComponent component)
throws IOException {
RendererUtils.checkParamValidity(facesContext, component, null);
if (component instanceof UISelectMany) {
HtmlRendererUtils.renderMenu(facesContext,
(UISelectMany) component,
isDisabled(facesContext,
component));
} else if (component instanceof UISelectOne) {
renderMenu(facesContext, (UISelectOne) component,
isDisabled(
facesContext, component));
} else {
throw new IllegalArgumentException("Unsupported
component class "
+ component.getClass().getName());
}
}
public void renderMenu(FacesContext facesContext, UISelectOne
uiComponent,
boolean disabled) throws IOException {
ResponseWriter writer = facesContext.getResponseWriter();
writer.startElement(HTML.SELECT_ELEM, uiComponent);
HtmlRendererUtils.writeIdIfNecessary(writer, uiComponent,
facesContext);
writer.writeAttribute(HTML.NAME_ATTR, uiComponent
.getClientId(facesContext), null);
List<SelectItem> selectItemList;
Converter converter;
selectItemList = RendererUtils
.getSelectItemList((UISelectOne) uiComponent);
converter = HtmlRendererUtils.findUIOutputConverterFailSafe(
facesContext, uiComponent);
int size = 1;
if (size == Integer.MIN_VALUE) {
// No size given (Listbox) --> size is number of select
items
writer.writeAttribute(HTML.SIZE_ATTR, Integer
.toString(selectItemList.size()), null);
} else {
writer.writeAttribute(HTML.SIZE_ATTR,
Integer.toString(size), null);
}
HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent,
HTML.SELECT_PASSTHROUGH_ATTRIBUTES_WITHOUT_DISABLED);
if (disabled) {
writer.writeAttribute(HTML.DISABLED_ATTR, Boolean.TRUE,
null);
}
if (HtmlRendererUtils.isReadOnly(uiComponent)) {
writer.writeAttribute(HTML.READONLY_ATTR,
HTML.READONLY_ATTR, null);
}
UISelectOne uiSelectOne = (UISelectOne) uiComponent;
/*The value was looked up during the validate phase.
* Even if the hole list of selectitmes know cheched by a
backing bean
* we have the origial selected object to compare. thats better
than
* to check against the index, which would lead to
* strange results
* */
Object lookupValue = uiSelectOne.getValue();
renderSelectOptions(facesContext, uiComponent, converter,
lookupValue, selectItemList, 0);
// bug #970747: force separate end tag
writer.writeText("", null);
writer.endElement(HTML.SELECT_ELEM);
}
public void renderSelectOptions(FacesContext context,
UIComponent component, Converter converter,
Object lookupObject, List<SelectItem> selectItemList,
Integer index)
throws IOException {
ResponseWriter writer = context.getResponseWriter();
for (Iterator<SelectItem> it = selectItemList.iterator();
it.hasNext();) {
SelectItem selectItem = it.next();
if (selectItem instanceof SelectItemGroup) {
writer.startElement(HTML.OPTGROUP_ELEM,
component);
writer.writeAttribute(HTML.LABEL_ATTR,
selectItem.getLabel(),
null);
SelectItem[] selectItems = ((SelectItemGroup)
selectItem)
.getSelectItems();
renderSelectOptions(context, component,
converter,
lookupObject,
Arrays.asList(selectItems), index);
writer.endElement(HTML.OPTGROUP_ELEM);
} else {
index++;
writer.write('\t');
writer.startElement(HTML.OPTION_ELEM,
component);
writer.writeAttribute(HTML.VALUE_ATTR,
index.toString(), null);
if (selectItem.getValue().equals(lookupObject))
{
writer.writeAttribute(HTML.SELECTED_ATTR,
HTML.SELECTED_ATTR,
null);
}
}
boolean disabled = selectItem.isDisabled();
if (disabled) {
writer.writeAttribute(HTML.DISABLED_ATTR,
HTML.DISABLED_ATTR,
null);
}
String labelClass = null;
boolean componentDisabled =
isTrue(component.getAttributes().get(
"disabled"));
if (componentDisabled || disabled) {
labelClass = (String)
component.getAttributes().get(
JSFAttr.DISABLED_CLASS_ATTR);
} else {
labelClass = (String)
component.getAttributes().get(
JSFAttr.ENABLED_CLASS_ATTR);
}
if (labelClass != null) {
writer.writeAttribute("class", labelClass,
"labelClass");
}
boolean escape;
if (component instanceof EscapeCapable) {
escape = ((EscapeCapable) component).isEscape();
} else {
escape =
RendererUtils.getBooleanAttribute(component,
JSFAttr.ESCAPE_ATTR, true); //
default is to escape
}
if (escape || selectItem.isEscape()) {
writer.writeText(selectItem.getLabel(), null);
} else {
writer.write(selectItem.getLabel());
}
writer.endElement(HTML.OPTION_ELEM);
}
}
private static boolean isTrue(Object obj) {
if (!(obj instanceof Boolean))
return false;
return ((Boolean) obj).booleanValue();
}
protected boolean isDisabled(FacesContext facesContext,
UIComponent uiComponent) {
// TODO: overwrite in extended HtmlMenuRenderer and check for
// enabledOnUserRole
if (uiComponent instanceof HtmlSelectManyMenu) {
return ((HtmlSelectManyMenu) uiComponent).isDisabled();
} else if (uiComponent instanceof HtmlSelectOneMenu) {
return ((HtmlSelectOneMenu) uiComponent).isDisabled();
} else {
return
org.apache.myfaces.shared_impl.renderkit.RendererUtils
.getBooleanAttribute(
uiComponent,
org.apache.myfaces.shared_impl.renderkit.html.HTML.DISABLED_ATTR,
false);
}
}
public void decode(FacesContext facesContext, UIComponent uiComponent) {
org.apache.myfaces.shared_impl.renderkit.RendererUtils
.checkParamValidity(facesContext, uiComponent,
null);
if (uiComponent instanceof UISelectMany) {
HtmlRendererUtils.decodeUISelectMany(facesContext,
uiComponent);
} else if (uiComponent instanceof UISelectOne) {
HtmlRendererUtils.decodeUISelectOne(facesContext,
uiComponent);
} else {
throw new IllegalArgumentException("Unsupported
component class "
+ uiComponent.getClass().getName());
}
}
public Object getConvertedValue(FacesContext facesContext,
UIComponent uiComponent, Object submittedValue)
throws ConverterException {
org.apache.myfaces.shared_impl.renderkit.RendererUtils
.checkParamValidity(facesContext, uiComponent,
null);
if (uiComponent instanceof UISelectMany) {
return
org.apache.myfaces.shared_impl.renderkit.RendererUtils
.getConvertedUISelectManyValue(facesContext,
(UISelectMany)
uiComponent, submittedValue);
} else if (uiComponent instanceof UISelectOne) {
UISelectOne d = (UISelectOne) uiComponent;
List<SelectItem> selectItemList = RendererUtils
.getSelectItemList(d);
if (submittedValue instanceof String){
Object x = lookup(facesContext,
selectItemList.toArray(new SelectItem[0]), Integer
.valueOf((String) submittedValue), 0);
return x;
} else {
//Log.info(submittedValue);
//return submittedValue;
//nothing was selected in the menu, so we need
to return null to pass the validation phase
return null;
}
} else {
throw new IllegalArgumentException("Unsupported
component class "
+ uiComponent.getClass().getName());
}
}
private Object lookup(FacesContext facesContext, SelectItem[]
selectItemList,
int submittedValue, Integer index) {
for (SelectItem selectItem :selectItemList) {
if (selectItem instanceof SelectItemGroup) {
SelectItem[] selectItems = ((SelectItemGroup)
selectItem)
.getSelectItems();
Object res = lookup(facesContext, selectItems,
submittedValue,
index);
if (res != null)
return res;
} else {
index++;
if (index.equals(submittedValue)) {
return selectItem.getValue();
}
}
}
return null;
}
}
> h:selectOneMenu should resolve non-string objects in the value property
> without a converter
> -------------------------------------------------------------------------------------------
>
> Key: MYFACES-1493
> URL: https://issues.apache.org/jira/browse/MYFACES-1493
> Project: MyFaces Core
> Issue Type: Improvement
> Affects Versions: 1.1.4
> Environment: JDK 1.5.0_08
> Reporter: Paul Norrie
> Priority: Minor
>
> h:selectOneMenu appears to require a converter if the object bound in the
> value field is not a java.lang.String.
> To reproduce:
> JSP snippet:
> <h:dataTable var="row" value="#{bean.rows}>
> <h:column>
> <h:selectOneMenu value="#{row.day}"/>
> <h:column>
> </h:dataTable>
> Java snippet (backing bean):
> private List<UserClass> rows;
> public List getRows(){
> return rows;
> }
> Java snippet (UserClass):
> static enum Day {MON, TUE, WED, THU, FRI, SAT, SUN};
> private Day day;
> public getDay(){
> return day;
> }
> Expected:
> the enum Day to be converted to a string and display either "MON", "TUE",
> etc...
> Actual:
> java.lang.IllegalArgumentException: Value is no String (class=UserClass$Day,
> value=MON)
> at
> org.apache.myfaces.shared_impl.renderkit.RendererUtils.getConvertedStringValue(RendererUtils.java:536)
> at
> org.apache.myfaces.shared_impl.renderkit.html.HtmlRendererUtils.getSubmittedOrSelectedValuesAsSet(HtmlRendererUtils.java:321)
> at
> org.apache.myfaces.shared_impl.renderkit.html.HtmlRendererUtils.internalRenderSelect(HtmlRendererUtils.java:296)
> at
> org.apache.myfaces.shared_impl.renderkit.html.HtmlRendererUtils.renderMenu(HtmlRendererUtils.java:252)
> at
> org.apache.myfaces.shared_impl.renderkit.html.HtmlMenuRendererBase.encodeEnd(HtmlMenuRendererBase.java:54)
> at
> javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:536)
> at
> org.apache.myfaces.shared_impl.renderkit.RendererUtils.renderChild(RendererUtils.java:442)
> at
> org.apache.myfaces.shared_impl.renderkit.RendererUtils.renderChildren(RendererUtils.java:419)
> at
> org.apache.myfaces.shared_impl.renderkit.RendererUtils.renderChild(RendererUtils.java:440)
> at
> org.apache.myfaces.shared_impl.renderkit.html.HtmlTableRendererBase.renderColumnBody(HtmlTableRendererBase.java:332)
> at
> org.apache.myfaces.shared_impl.renderkit.html.HtmlTableRendererBase.encodeColumnChild(HtmlTableRendererBase.java:301)
> at
> org.apache.myfaces.shared_impl.renderkit.html.HtmlTableRendererBase.encodeInnerHtml(HtmlTableRendererBase.java:277)
> at
> org.apache.myfaces.shared_impl.renderkit.html.HtmlTableRendererBase.encodeChildren(HtmlTableRendererBase.java:123)
> at
> javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:524)
> The RI and ADF Faces will quite happily work, however myfaces doc's seem to
> mean that a convertor is needed.
> See also http://www.mail-archive.com/[EMAIL PROTECTED]/msg29588.html
> This is a pain - could it be fixed please?
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.