如何覆盖h:selectOneRadio渲染器? jsf-impl中的渲染器类在哪里?

时间:2013-08-22 19:35:50

标签: jsf jsf-2

是否可以覆盖<h:selectOneRadio>使用的渲染器?我试图从JSF 2.2的jsf-impl包中找到该类,但没有找到它。我想要这样做的原因是摆脱它生成的表。

2 个答案:

答案 0 :(得分:4)

  

是否可以覆盖h使用的渲染器:selectOneRadio?

是的,肯定是的。否则,PrimeFaces等UI组件库可能不存在。


  

我试图从jsf-impl包中找到该类,但没有找到它。

确切的类取决于您正在使用的JSF实现。如果它是Mojarra,那么它就是com.sun.faces.renderkit.html_basic.RadioRenderer类。如果它是MyFaces,则它是org.apache.myfaces.renderkit.html.HtmlRadioRenderer类。

为了正确覆盖它,只需在必要时扩展类和覆盖方法,并在faces-config.xml中按如下方式注册:

<render-kit>
    <renderer>
        <component-family>javax.faces.SelectOne</component-family>
        <renderer-type>javax.faces.Radio</renderer-type>
        <renderer-class>com.example.MyRadioRenderer</renderer-class>
    </renderer>
</render-kit>

请记住,您通过这种方式将渲染器紧密耦合到特定的JSF impl / version。这样的扩展渲染器与不同的JSF实现不兼容(即,当您用MyFaces替换Mojarra时,您的应用程序不会部署),并且当当前的JSF实现更新到更新版本时可能会中断。如果您担心这一点,请考虑完全从头开始编写渲染器,如PrimeFaces et.al.做。


  

我想要这样做的原因是摆脱它生成的表。

考虑查看TomahawkPrimeFaces而不是重新发明轮子。他们分别有一个<t:selectOneRadio layout="spread"><t:radio><p:selectOneRadio layout="custom"><p:radioButton>,可让您随心所欲地定位这些内容。

另见:

答案 1 :(得分:1)

我添加了

  <render-kit>
        <renderer>
            <component-family>javax.faces.SelectOne</component-family>
            <renderer-type>javax.faces.Radio</renderer-type>
            <renderer-class>com.sial.ecommerce.configurator.ui.model.RadioRendererWithoutDataTable</renderer-class>
        </renderer>
    </render-kit>

faces-config.xml

并创建了一个扩展com.sun.faces.renderkit.html_basic.RadioRenderer的类。我确实覆盖了方法encodeEnd,然后注释了添加table元素的代码。

public class RadioRendererWithoutDataTable extends com.sun.faces.renderkit.html_basic.RadioRenderer {
    @Override
    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {

        rendererParamsNotNull(context, component);

        if (!shouldEncode(component)) {
            return;
        }

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

        String alignStr;
        Object borderObj;
        boolean alignVertical = false;
        int border = 0;

        if (null != (alignStr = (String) component.getAttributes().get("layout"))) {
            alignVertical = alignStr.equalsIgnoreCase("pageDirection");
        }
        if (null != (borderObj = component.getAttributes().get("border"))) {
            border = (Integer) borderObj;
        }

        Converter converter = null;
        if (component instanceof ValueHolder) {
            converter = ((ValueHolder) component).getConverter();
        }

//      renderBeginText(component, border, alignVertical, context, true);

        Iterator<SelectItem> items = RenderKitUtils.getSelectItems(context, component);

        Object currentSelections = getCurrentSelectedValues(component);
        Object[] submittedValues = getSubmittedSelectedValues(component);
        Map<String, Object> attributes = component.getAttributes();
        OptionComponentInfo optionInfo = new OptionComponentInfo((String) attributes.get("disabledClass"),
                (String) attributes.get("enabledClass"), (String) attributes.get("unselectedClass"),
                (String) attributes.get("selectedClass"), Util.componentIsDisabled(component), isHideNoSelection(component));
        int idx = -1;
        while (items.hasNext()) {
            SelectItem curItem = items.next();
            idx++;
            // If we come across a group of options, render them as a nested
            // table.
            if (curItem instanceof SelectItemGroup) {
                // write out the label for the group.
                if (curItem.getLabel() != null) {
//                  if (alignVertical) {
//                      writer.startElement("tr", component);
//                  }
                    //writer.startElement("td", component);
                    writer.writeText(curItem.getLabel(), component, "label");
//                  writer.endElement("td");
//                  if (alignVertical) {
//                      writer.endElement("tr");
//                  }

                }
//              if (alignVertical) {
//                  writer.startElement("tr", component);
//              }
//              writer.startElement("td", component);
//              writer.writeText("\n", component, null);
//              renderBeginText(component, 0, alignVertical, context, false);
                // render options of this group.
                SelectItem[] itemsArray = ((SelectItemGroup) curItem).getSelectItems();
                for (int i = 0; i < itemsArray.length; ++i) {
                    renderOption(context, component, converter, itemsArray[i], currentSelections, submittedValues, alignVertical, i,
                            optionInfo);
                }
//              renderEndText(component, alignVertical, context);
//              writer.endElement("td");
//              if (alignVertical) {
//                  writer.endElement("tr");
//                  writer.writeText("\n", component, null);
//              }
            } else {
                renderOption(context, component, converter, curItem, currentSelections, submittedValues, alignVertical, idx, optionInfo);
            }
        }

        //renderEndText(component, alignVertical, context);
    }

然后它对我有用。

当我给出

<h:selectOneRadio >
<f:selectItem itemValue="1" itemLabel="Item 1" />
<f:selectItem itemValue="2" itemLabel="Item 2" />
</h:selectOneRadio>

在我的jsf页面中。

转换为

<input type="radio" name="bulkForm:j_idt224" id="bulkForm:j_idt224:0" value="1"><label for="bulkForm:j_idt224:0"> Item 1</label>

<input type="radio" name="bulkForm:j_idt224" id="bulkForm:j_idt224:1" value="2"><label for="bulkForm:j_idt224:1"> Item 2</label>

这就是我需要的。

相关问题