Как переопределить рендер h:selectOneRadio? Где находится класс рендерера в jsf-impl?
Можно ли переопределить рендерер, используемый <h:selectOneRadio>
? Я пытался найти класс из пакета jsf-impl JSF 2.2, но не нашел его. Причина, по которой я хочу это сделать, состоит в том, чтобы избавиться от создаваемой таблицы.
2 ответа
Можно ли переопределить средство визуализации, используемое h: selectOneRadio?
Да, конечно, это так. В противном случае библиотеки компонентов пользовательского интерфейса, такие как PrimeFaces, не могли бы существовать.
Я пытался найти класс из пакета jsf-impl, но не нашел его.
Точный класс зависит от используемой вами реализации JSF. Если это Мохарра, то это 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. Такой расширенный рендерер несовместим с другой реализацией JSF (т. Е. Ваше приложение не будет развернуто, когда вы когда-нибудь замените Mojarra на MyFaces) и может сломаться, когда текущая реализация JSF будет обновлена до более новой версии. Если вы беспокоитесь об этом, подумайте над тем, чтобы написать рендерер с нуля, как PrimeFaces et.al. делать.
Причина, по которой я хочу это сделать, состоит в том, чтобы избавиться от создаваемой таблицы.
Подумайте о томагавке или PrimeFaces, а не изобретайте велосипед. Они имеют соответственно <t:selectOneRadio layout="spread"><t:radio>
а также <p:selectOneRadio layout="custom"><p:radioButton>
что позволяет вам позиционировать эти вещи везде, где вы хотите.
Смотрите также:
Я добавил
<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>
что было то, что мне нужно.