我已经覆盖了 SelectOneMenuRenderer 来为这个组件添加 OptionGroup-Support。现在显示选项组。伟大的!
但是当我有一个带有选项组的选择并单击此菜单中的一个项目时:
- 选择了下面的 SelectItem(在第一个选项组之后)
- 选择了下面的 SelectItem 两个(在第二个选项组之后)
- ...
一些 javascript 在这里把事情搞砸了,但我无法弄清楚究竟是哪个以及在哪里。
代码:
package org.primefaces.component.selectonemenu;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.faces.component.UIComponent;
import javax.faces.component.UISelectOne;
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.primefaces.component.column.Column;
import org.primefaces.renderkit.SelectOneRenderer;
import org.primefaces.util.ComponentUtils;
public class SelectOneMenuRenderer extends SelectOneRenderer {
@Override
public void decode(final FacesContext context, final UIComponent component) {
if (!shouldDecode(component)) {
return;
}
SelectOneMenu menu = (SelectOneMenu)component;
if (menu.isEditable()) {
Map<String, String> params = context.getExternalContext().getRequestParameterMap();
decodeBehaviors(context, menu);
menu.setSubmittedValue(params.get(menu.getClientId(context) + "_editableInput"));
}
else {
super.decode(context, component);
}
}
@Override
public Object getConvertedValue(final FacesContext context, final UIComponent component,
final Object submittedValue) throws ConverterException
{
return context.getRenderKit().getRenderer("javax.faces.SelectOne", "javax.faces.Menu")
.getConvertedValue(context, component, submittedValue);
}
@Override
public void encodeEnd(final FacesContext context, final UIComponent component) throws IOException {
SelectOneMenu menu = (SelectOneMenu)component;
encodeMarkup(context, menu);
encodeScript(context, menu);
}
protected void encodeMarkup(final FacesContext context, final SelectOneMenu menu) throws IOException {
boolean isOptionGroup = false;
ResponseWriter writer = context.getResponseWriter();
List<SelectItem> selectItems = getSelectItems(context, menu);
String clientId = menu.getClientId(context);
Converter converter = menu.getConverter();
Object values = getValues(menu);
Object submittedValues = getSubmittedValues(menu);
boolean valid = menu.isValid();
String style = menu.getStyle();
String styleClass = menu.getStyleClass();
styleClass = styleClass == null ? SelectOneMenu.STYLE_CLASS : SelectOneMenu.STYLE_CLASS + " "
+ styleClass;
styleClass = !valid ? styleClass + " ui-state-error" : styleClass;
styleClass = menu.isDisabled() ? styleClass + " ui-state-disabled" : styleClass;
writer.startElement("div", menu);
writer.writeAttribute("id", clientId, "id");
writer.writeAttribute("class", styleClass, "styleclass");
if (style != null) {
writer.writeAttribute("style", style, "style");
}
// filter selectItems // values
List<SelectItem> selectGroupedItems = new ArrayList<SelectItem>();
for (Object item : selectItems) {
if (item instanceof SelectItemGroup) {
isOptionGroup = true; // Flag, um den (Render-)Modus auf "Optiongroup" umzuschalten
((SelectItemGroup)item).setNoSelectionOption(true);
((SelectItemGroup)item).setDisabled(true);
selectGroupedItems.add((SelectItem)item); // Nicht: SelectItemGroup
SelectItem[] innerItems = ((SelectItemGroup)item).getSelectItems();
for (SelectItem innerItem : innerItems) {
selectGroupedItems.add(innerItem);
}
continue;
}
selectGroupedItems.add((SelectItem)item);
}
// Encode tags
encodeInput(context, menu, clientId, selectGroupedItems, values, submittedValues, converter);
encodeLabel(context, menu, selectGroupedItems);
encodeMenuIcon(context, menu, valid);
encodePanel(context, menu, selectGroupedItems, isOptionGroup);
writer.endElement("div");
}
protected void encodeInput(final FacesContext context, final SelectOneMenu menu, final String clientId,
final List<SelectItem> selectItems, final Object values, final Object submittedValues,
final Converter converter) throws IOException
{
ResponseWriter writer = context.getResponseWriter();
String inputId = clientId + "_input";
writer.startElement("div", menu);
writer.writeAttribute("class", "ui-helper-hidden-accessible", null);
writer.startElement("select", menu);
writer.writeAttribute("id", inputId, "id");
writer.writeAttribute("name", inputId, null);
if (menu.isDisabled()) {
writer.writeAttribute("disabled", "disabled", null);
}
if (menu.getTabindex() != null) {
writer.writeAttribute("tabindex", menu.getTabindex(), null);
}
if (menu.getOnkeydown() != null) {
writer.writeAttribute("onkeydown", menu.getOnkeydown(), null);
}
if (menu.getOnkeyup() != null) {
writer.writeAttribute("onkeyup", menu.getOnkeyup(), null);
}
encodeSelectItems(context, menu, selectItems, values, submittedValues, converter);
writer.endElement("select");
writer.endElement("div");
}
protected void encodeLabel(final FacesContext context, final SelectOneMenu menu,
final List<SelectItem> selectItems) throws IOException
{
ResponseWriter writer = context.getResponseWriter();
String valueToRender = ComponentUtils.getValueToRender(context, menu);
if (menu.isEditable()) {
writer.startElement("input", null);
writer.writeAttribute("type", "text", null);
writer.writeAttribute("name", menu.getClientId() + "_editableInput", null);
writer.writeAttribute("class", SelectOneMenu.LABEL_CLASS, null);
writer.writeAttribute("tabindex", -1, null);
writer.writeAttribute("autocomplete", "off", null);
if (menu.isDisabled()) {
writer.writeAttribute("disabled", "disabled", null);
}
if (valueToRender != null) {
writer.writeAttribute("value", valueToRender, null);
}
writer.endElement("input");
}
else {
writer.startElement("label", null);
writer.writeAttribute("id", menu.getClientId() + "_label", null);
writer.writeAttribute("class", SelectOneMenu.LABEL_CLASS, null);
writer.write(" ");
writer.endElement("label");
}
}
protected void encodeMenuIcon(final FacesContext context, final SelectOneMenu menu, final boolean valid)
throws IOException
{
ResponseWriter writer = context.getResponseWriter();
String iconClass = valid ? SelectOneMenu.TRIGGER_CLASS : SelectOneMenu.TRIGGER_CLASS + " ui-state-error";
writer.startElement("div", menu);
writer.writeAttribute("class", iconClass, null);
writer.startElement("span", menu);
writer.writeAttribute("class", "ui-icon ui-icon-triangle-1-s", null);
writer.endElement("span");
writer.endElement("div");
}
protected void encodePanel(final FacesContext context, final SelectOneMenu menu,
final List<SelectItem> selectItems, final boolean isOptionGroup) throws IOException
{
ResponseWriter writer = context.getResponseWriter();
boolean customContent = menu.getVar() != null;
int height = calculatePanelHeight(menu, selectItems.size());
String panelStyle = menu.getPanelStyle() != null ? menu.getPanelStyle() : "";
String panelStyleClass = menu.getPanelStyleClass();
panelStyleClass = panelStyleClass == null ? SelectOneMenu.PANEL_CLASS : SelectOneMenu.PANEL_CLASS + " "
+ panelStyleClass;
if (height != -1) {
panelStyle += ";height:" + height + "px";
}
writer.startElement("div", null);
writer.writeAttribute("id", menu.getClientId(context) + "_panel", null);
writer.writeAttribute("class", panelStyleClass, null);
if (!isValueEmpty(panelStyle)) {
writer.writeAttribute("style", panelStyle, null);
}
if (customContent) {
writer.startElement("table", menu);
writer.writeAttribute("class", SelectOneMenu.TABLE_CLASS, null);
writer.startElement("tbody", menu);
encodeOptionsAsTable(context, menu, selectItems, isOptionGroup);
writer.endElement("tbody");
writer.endElement("table");
}
else {
writer.startElement("ul", menu);
writer.writeAttribute("class", SelectOneMenu.LIST_CLASS, null);
encodeOptionsAsList(context, menu, selectItems, isOptionGroup);
writer.endElement("ul");
}
writer.endElement("div");
}
protected void encodeOptionsAsTable(final FacesContext context, final SelectOneMenu menu,
final List<SelectItem> selectItems, final boolean isOptionGroup) throws IOException
{
ResponseWriter writer = context.getResponseWriter();
String var = menu.getVar();
List<Column> columns = menu.getColums();
Object value = menu.getValue();
for (SelectItem selectItem : selectItems) {
Object itemValue = selectItem.getValue();
context.getExternalContext().getRequestMap().put(var, selectItem.getValue());
writer.startElement("tr", null);
writer.writeAttribute("class", SelectOneMenu.ROW_CLASS, null);
if (selectItem.getDescription() != null) {
writer.writeAttribute("title", selectItem.getDescription(), null);
}
if (itemValue instanceof String) {
writer.startElement("td", null);
writer.writeAttribute("colspan", columns.size(), null);
if (isOptionGroup) {
if (selectItem instanceof SelectItemGroup) {
writer.writeAttribute("class", "ui-selectonemenu-optiongroup-header", null);
}
else {
writer.writeAttribute("class", SelectOneMenu.ITEM_CLASS + " ui-selectonemenu-optiongroup-items",
null);
}
}
writer.writeText(selectItem.getLabel(), null);
writer.endElement("td");
}
else {
for (Column column : columns) {
writer.startElement("td", null);
column.encodeAll(context);
writer.endElement("td");
}
}
writer.endElement("tr");
}
context.getExternalContext().getRequestMap().put(var, null);
}
protected void encodeOptionsAsList(final FacesContext context, final SelectOneMenu menu,
final List<SelectItem> selectItems, final boolean isOptionGroup) throws IOException
{
ResponseWriter writer = context.getResponseWriter();
Object value = menu.getValue();
for (int i = 0; i < selectItems.size(); i++) {
SelectItem selectItem = selectItems.get(i);
String itemLabel = selectItem.getLabel();
itemLabel = isValueBlank(itemLabel) ? " " : itemLabel;
writer.startElement("li", null);
if (selectItem instanceof SelectItemGroup) {
writer.writeAttribute("class", " ui-selectonemenu-optiongroup-header", null);
}
else {
if (isOptionGroup) {
writer.writeAttribute("class", SelectOneMenu.ITEM_CLASS + " ui-selectonemenu-optiongroup-items",
null);
}
else {
writer.writeAttribute("class", SelectOneMenu.ITEM_CLASS, null);
}
}
if (selectItem.getDescription() != null) {
writer.writeAttribute("title", selectItem.getDescription(), null);
}
if (itemLabel.equals(" ")) {
writer.write(itemLabel);
}
else {
if (selectItem.isEscape()) {
writer.writeText(itemLabel, "value");
}
else {
writer.write(itemLabel);
}
}
writer.endElement("li");
}
}
protected void encodeScript(final FacesContext context, final SelectOneMenu menu) throws IOException {
ResponseWriter writer = context.getResponseWriter();
String clientId = menu.getClientId(context);
startScript(writer, clientId);
writer.write("$(function(){");
writer.write("PrimeFaces.cw('SelectOneMenu','" + menu.resolveWidgetVar() + "',{");
writer.write("id:'" + clientId + "'");
writer.write(",effect:'" + menu.getEffect() + "'");
if (menu.getEffectDuration() != 400) {
writer.write(",effectDuration:" + menu.getEffectDuration());
}
if (menu.isEditable()) {
writer.write(",editable:true");
}
if (menu.getOnchange() != null) {
writer.write(",onchange:function() {" + menu.getOnchange() + "}");
}
encodeClientBehaviors(context, menu);
writer.write("});});");
endScript(writer);
}
protected void encodeSelectItems(final FacesContext context, final SelectOneMenu menu,
final List<SelectItem> selectItems, final Object values, final Object submittedValues,
final Converter converter) throws IOException
{
for (SelectItem selectItem : selectItems) {
encodeOption(context, menu, selectItem, values, submittedValues, converter);
}
}
protected void encodeOption(final FacesContext context, final SelectOneMenu menu, final SelectItem option,
final Object values, final Object submittedValues, final Converter converter) throws IOException
{
ResponseWriter writer = context.getResponseWriter();
String itemValueAsString = getOptionAsString(context, menu, converter, option.getValue());
boolean disabled = option.isDisabled();
Object valuesArray;
Object itemValue;
if (submittedValues != null) {
valuesArray = submittedValues;
itemValue = itemValueAsString;
}
else {
valuesArray = values;
itemValue = option.getValue();
}
boolean selected = isSelected(context, menu, itemValue, valuesArray, converter);
if (option.isNoSelectionOption() && values != null && !selected) {
return;
}
String elem = "option";
if (option instanceof SelectItemGroup) {
selected = false;
}
writer.startElement(elem, null);
writer.writeAttribute("value", itemValueAsString, null);
if (disabled) {
writer.writeAttribute("disabled", "disabled", null);
}
if (selected) {
writer.writeAttribute("selected", "selected", null);
}
if (option.isEscape()) {
writer.writeText(option.getLabel(), "value");
}
else {
writer.write(option.getLabel());
}
writer.endElement(elem);
}
protected int calculatePanelHeight(final SelectOneMenu menu, final int itemSize) {
int height = menu.getHeight();
if (height != Integer.MAX_VALUE) {
return height;
}
else if (itemSize > 10) {
return 200;
}
return -1;
}
@Override
public void encodeChildren(final FacesContext facesContext, final UIComponent component) throws IOException
{
// Rendering happens on encodeEnd
}
@Override
public boolean getRendersChildren() {
return true;
}
@Override
protected String getSubmitParam(final FacesContext context, final UISelectOne selectOne) {
return selectOne.getClientId(context) + "_input";
}
}
任何提示是什么原因造成的?
强尼