2014-12-05 28 views
0

我要当菜单的明文选项设置为true像JSF selectOneMenu用于:延长MenuRenderer的时候有一个项目

<span ...>An item</span> 

而不是

<select ...> 
<option ...>An item</option> 
</select> 

显示的东西显示一个纯文本并且里面只有一个SelectItem:

<h:selectOneMenu plainText="true" ...> 
<f:selectItems ... /> <!-- contains one item --> 
</h:selectOneMenu> 

我试过创建一个自MenuRenderer扩展的自定义渲染器,但它的代码并不是真正可追加的。你能帮忙吗?谢谢。

+0

当有一个以上的元素,菜单应呈现 – Vladiator 2014-12-05 20:33:46

+0

我不想每当我需要它时都要做 – Vladiator 2014-12-05 20:58:35

回答

0

我们需要扩展com.sun.faces.renderkit.html_basic.MenuRenderer和覆盖renderSelectrenderOption方法。其代码大部分都是从父级复制的。 私有布尔plainText当我们需要将元素显示为一个范围时为true。 在renderSelect的begginning我们补充一点:

plainText = "true".equalsIgnoreCase((String) component.getAttributes().get("plainText")); 
if (plainText) { 
    SelectItemsIterator<SelectItem> items = RenderKitUtils.getSelectItems(context, component); 
    items.next(); 
    plainText = !items.hasNext(); 
} 

它首先检查是否明文选项设置为,比它检查是否有是唯一的选择信息。我认为这部分可以优化。取而代之的

writer.startElement("select", component); 

我们应该写

if (plainText) { 
    writer.startElement("span", component); 
} else { 
    writer.startElement("select", component); 
} 

而且做同样的writer.endElement。

renderOption的中间,我们添加了一个代码,只需打印出没有任何标签和离开的唯一选项。

if (plainText) { 
    if (curItem.isEscape()) { 
     String label = curItem.getLabel(); 
     if (label == null) { 
      label = valueString; 
     } 
     writer.writeText(label, component, "label"); 
    } else { 
     writer.write(curItem.getLabel()); 
    } 
    writer.writeText("\n", component, null); 
    return true; 
} 

所有代码:

import com.sun.faces.io.FastStringWriter; 
import com.sun.faces.renderkit.Attribute; 
import com.sun.faces.renderkit.AttributeManager; 
import com.sun.faces.renderkit.RenderKitUtils; 
import com.sun.faces.renderkit.SelectItemsIterator; 
import com.sun.faces.renderkit.html_basic.MenuRenderer; 

import javax.faces.component.UIComponent; 
import javax.faces.context.FacesContext; 
import javax.faces.context.ResponseWriter; 
import javax.faces.convert.Converter; 
import javax.faces.model.SelectItem; 
import java.io.IOException; 
import java.util.logging.Level; 

public class ExtendedMenuRenderer extends MenuRenderer { 
    private boolean plainText; 

    private static final Attribute[] ATTRIBUTES = 
      AttributeManager.getAttributes(AttributeManager.Key.SELECTMANYMENU); 

    @Override 
    protected void renderSelect(FacesContext context, 
           UIComponent component) throws IOException { 
     plainText = "true".equalsIgnoreCase((String) component.getAttributes().get("plainText")); 
     if (plainText) { 
      SelectItemsIterator<SelectItem> items = RenderKitUtils.getSelectItems(context, component); 
      items.next(); 
      plainText = !items.hasNext(); 
     } 

     ResponseWriter writer = context.getResponseWriter(); 
     assert (writer != null); 

     if (logger.isLoggable(Level.FINER)) { 
      logger.log(Level.FINER, "Rendering 'select'"); 
     } 
     if (plainText) { 
      writer.startElement("span", component); 
     } else { 
      writer.startElement("select", component); 
     } 
     writeIdAttributeIfNecessary(context, writer, component); 
     writer.writeAttribute("name", component.getClientId(context), 
       "clientId"); 
     // render styleClass attribute if present. 
     String styleClass; 
     if (null != 
       (styleClass = 
         (String) component.getAttributes().get("styleClass"))) { 
      writer.writeAttribute("class", styleClass, "styleClass"); 
     } 
     if (!getMultipleText(component).equals("")) { 
      writer.writeAttribute("multiple", true, "multiple"); 
     } 

     // Determine how many option(s) we need to render, and update 
     // the component's "size" attribute accordingly; The "size" 
     // attribute will be rendered as one of the "pass thru" attributes 
     SelectItemsIterator<SelectItem> items = RenderKitUtils.getSelectItems(context, component); 

     // render the options to a buffer now so that we can determine 
     // the size 
     FastStringWriter bufferedWriter = new FastStringWriter(128); 
     context.setResponseWriter(writer.cloneWithWriter(bufferedWriter)); 
     int count = renderOptions(context, component, items); 
     context.setResponseWriter(writer); 
     // If "size" is *not* set explicitly, we have to default it correctly 
     Integer size = (Integer) component.getAttributes().get("size"); 
     if (size == null || size == Integer.MIN_VALUE) { 
      size = count; 
     } 
     writeDefaultSize(writer, size); 

     RenderKitUtils.renderPassThruAttributes(context, 
       writer, 
       component, 
       ATTRIBUTES, 
       getNonOnChangeBehaviors(component)); 
     RenderKitUtils.renderXHTMLStyleBooleanAttributes(writer, 
       component); 

     RenderKitUtils.renderOnchange(context, component, false); 

     // Now, write the buffered option content 
     writer.write(bufferedWriter.toString()); 

     if (plainText) { 
      writer.endElement("span"); 
     } else { 
      writer.endElement("select"); 
     } 

    } 

    @Override 
    protected boolean renderOption(FacesContext context, 
            UIComponent component, 
            UIComponent selectComponent, 
            Converter converter, 
            SelectItem curItem, 
            Object currentSelections, 
            Object[] submittedValues, 
            OptionComponentInfo optionInfo) throws IOException { 

     Object valuesArray; 
     Object itemValue; 
     String valueString = getFormattedValue(context, component, 
       curItem.getValue(), converter); 
     boolean containsValue; 
     if (submittedValues != null) { 
      containsValue = containsaValue(submittedValues); 
      if (containsValue) { 
       valuesArray = submittedValues; 
       itemValue = valueString; 
      } else { 
       valuesArray = currentSelections; 
       itemValue = curItem.getValue(); 
      } 
     } else { 
      valuesArray = currentSelections; 
      itemValue = curItem.getValue(); 
     } 

     boolean isSelected = isSelected(context, component, itemValue, valuesArray, converter); 
     if (optionInfo.isHideNoSelection() 
       && curItem.isNoSelectionOption() 
       && currentSelections != null 
       && !isSelected) { 
      return false; 
     } 

     ResponseWriter writer = context.getResponseWriter(); 
     assert (writer != null); 
     writer.writeText("\t", component, null); 

     if (plainText) { 
      if (curItem.isEscape()) { 
       String label = curItem.getLabel(); 
       if (label == null) { 
        label = valueString; 
       } 
       writer.writeText(label, component, "label"); 
      } else { 
       writer.write(curItem.getLabel()); 
      } 
      writer.writeText("\n", component, null); 
      return true; 
     } 

     writer.startElement("option", (null != selectComponent) ? selectComponent : component); 
     writer.writeAttribute("value", valueString, "value"); 

     if (isSelected) { 
      writer.writeAttribute("selected", true, "selected"); 
     } 

     // if the component is disabled, "disabled" attribute would be rendered 
     // on "select" tag, so don't render "disabled" on every option. 
     if ((!optionInfo.isDisabled()) && curItem.isDisabled()) { 
      writer.writeAttribute("disabled", true, "disabled"); 
     } 

     String labelClass; 
     if (optionInfo.isDisabled() || curItem.isDisabled()) { 
      labelClass = optionInfo.getDisabledClass(); 
     } else { 
      labelClass = optionInfo.getEnabledClass(); 
     } 
     if (labelClass != null) { 
      writer.writeAttribute("class", labelClass, "labelClass"); 
     } 

     if (curItem.isEscape()) { 
      String label = curItem.getLabel(); 
      if (label == null) { 
       label = valueString; 
      } 
      writer.writeText(label, component, "label"); 
     } else { 
      writer.write(curItem.getLabel()); 
     } 
     writer.endElement("option"); 
     writer.writeText("\n", component, null); 
     return true; 
    } 
} 

faces-config.xml中添加:

<render-kit> 
    <renderer> 
     <component-family>javax.faces.SelectOne</component-family> 
     <renderer-type>javax.faces.Menu</renderer-type> 
     <renderer-class>ru.mycityseason.extentions.ExtendedMenuRenderer</renderer-class> 
    </renderer> 
</render-kit> 
相关问题