Добавление поддержки пользовательского атрибута (HTML5) компоненту JSF 2.0 UIInput
Я пытаюсь написать рендерер, который обрабатывал бы атрибут placeholder
на компоненте <h:inputText>
.
Я отправился на этот путь после прочтения JSF 2.0 удаляет необходимые атрибуты HTML5, и это кажется правильным. Здесь мой пользовательский рендеринг
public class InputRenderer extends com.sun.faces.renderkit.html_basic.TextRenderer{
@Override
public void encodeBegin(FacesContext context, UIComponent component)
throws IOException {
System.out.println("Rendering :"+component.getClientId());
String placeholder = (String)component.getAttributes().get("placeholder");
if(placeholder != null) {
ResponseWriter writer = context.getResponseWriter();
writer.writeAttribute("placeholder", placeholder, "placeholder");
}
super.encodeBegin(context, component);
}
@Override
public void decode(FacesContext context, UIComponent component) {
super.decode(context, component);
}
@Override
public void encodeEnd(FacesContext context, UIComponent component)
throws IOException {
super.encodeEnd(context, component);
}
}
И этот рендерер зарегистрирован в конфигурациях лиц как
<render-kit>
<renderer>
<component-family>javax.faces.Input</component-family>
<renderer-type>javax.faces.Text</renderer-type>
<renderer-class>com.example.renderer.InputRenderer</renderer-class>
</renderer>
</render-kit>
Это нормально зарегистрировано, никаких проблем нет.
Я намерен обработать атрибут placeholder
, вставить его, а затем делегировать обработку супер. Мой выше код не работает, потому что я вставляю атрибут в неправильном месте. Он должен быть вставлен после выполнения writer.startElement('input')
. Однако элемент startElement должен происходить где-то в методе super encodeBegin()
. Итак, как мне вставить пользовательский атрибут ( "placeholder" в этом случае), а затем продолжить поток выполнения?
NB: приведенный выше код добавляет атрибут placeholder
, но не к входящему компоненту, на который я намереваюсь, он записывает его родительскому элементу ввода (поскольку я пытаюсь написать атрибут до того, как сам компонент фактически написанный в потоке, он применяет атрибут к текущему компоненту)
Ответы
Ответ 1
Это мой путь. Я добавил атрибуты placeholder и data-theme. Если вы хотите добавить дополнительные атрибуты, просто добавьте его имя в массив атрибутов.
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import com.sun.faces.renderkit.html_basic.TextRenderer;
public class InputRender extends TextRenderer {
@Override
protected void getEndTextToRender(FacesContext context,
UIComponent component,
String currentValue)
throws java.io.IOException{
String [] attributes = {"placeholder","data-theme"};
ResponseWriter writer = context.getResponseWriter();
for(String attribute : attributes)
{
String value = (String)component.getAttributes().get(attribute);
if(value != null) {
writer.writeAttribute(attribute, value, attribute);
}
}
super.getEndTextToRender(context, component, currentValue);
}
}
Вы должны добавить это в файл faces-config.xml.
<render-kit>
<renderer>
<component-family>javax.faces.Input</component-family>
<renderer-type>javax.faces.Text</renderer-type>
<renderer-class>your.package.InputRenderer</renderer-class>
</renderer>
</render-kit>
Ответ 2
Вы можете просто переопределить метод ResponseWriters startElement, этот метод вызывается только один раз, а затем вы можете восстановить исходный объект respewriter.
import javax.faces.context.*;
import java.io.IOException;
public class InputRenderer extends com.sun.faces.renderkit.html_basic.TextRenderer{
// Put all of the attributes you want to render here...
private static final String[] ATTRIBUTES = {"required","placeholder"};
@Override
protected void getEndTextToRender(FacesContext context,
UIComponent component, String currentValue) throws IOException {
final ResponseWriter originalResponseWriter = context.getResponseWriter();
context.setResponseWriter(new ResponseWriterWrapper() {
@Override
// As of JSF 1.2 this method is now public.
public ResponseWriter getWrapped() {
return originalResponseWriter;
}
@Override
public void startElement(String name, UIComponent component)
throws IOException {
super.startElement(name, component);
if ("input".equals(name)) {
for (String attribute : ATTRIBUTES)
{
Object value = component.getAttributes().get(attribute);
if (value != null)
{
super.writeAttribute(attribute,value,attribute);
}
}
}
});
super.getEndTextToRender(context, component, currentValue);
context.setResponseWriter(originalResponseWriter); // Restore original writer.
}
}
Ответ 3
И переопределить для MyFaces 2.0.8 +
package com.hsop.abc.eld;
import java.io.IOException;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import org.apache.myfaces.renderkit.html.HtmlTextRenderer;
public class InputRenderer extends HtmlTextRenderer
{
@Override
protected void renderInputBegin(FacesContext context, UIComponent component)
throws IOException
{
// TODO Auto-generated method stub
super.renderInputBegin(context, component);
Object placeholder = component.getAttributes().get("placeholder");
if(placeholder != null) {
ResponseWriter writer = context.getResponseWriter();
writer.writeAttribute("placeholder", placeholder, "placeholder");
}
}
}