Si necesita un componente específico que utiliza un representador diferente de <p:autoComplete>
, entonces no puede crear un componente personalizado con su propia familia y tipo de componente. Todavía puede ampliar las PrimeFaces AutoComplete
(y su procesador) para guardar un código repetitivo.
En el componente personalizado, debe proporcionar getters para esos atributos. También podría especificar configuradores, de esta manera siempre puede anular los valores predeterminados en el lado de la vista. Esos getters/setters deberían a su vez delegar en StateHelper
.
Solo hay un pequeño problema con los atributos x-webkit-*
. El -
es un carácter ilegal en los identificadores de Java. Por lo tanto, debe cambiar el nombre de los getters/setters y cambiar el renderizador de alguna manera, ya que el renderizador estándar confía en que el nombre de la propiedad del componente sea exactamente el mismo que el nombre del atributo de la etiqueta. Update: Entiendo que x-webkit-speech
solo debe representarse como está (por lo tanto, no es necesario getter/setter) y que x-webkit-grammer
es en realidad un error tipográfico, debería ser x-webkit-grammar
.
Así es como el componente SiteSearch
puede verse como:
@FacesComponent(SiteSearch.COMPONENT_TYPE)
public class SiteSearch extends AutoComplete {
public static final String COMPONENT_FAMILY = "com.example";
public static final String COMPONENT_TYPE = "com.example.SiteSearch";
private enum PropertyKeys {
grammar, onspeechchange, placeholder
}
@Override
public String getFamily() {
return COMPONENT_FAMILY;
}
@Override
public String getRendererType() {
return SiteSearchRenderer.RENDERER_TYPE;
}
public String getGrammar() {
return (String) getStateHelper().eval(PropertyKeys.grammar, "builtin:search");
}
public void setGrammar(String grammar) {
getStateHelper().put(PropertyKeys.grammar, grammar);
}
public String getOnspeechchange() {
return (String) getStateHelper().eval(PropertyKeys.onspeechchange, "submit()");
}
public void setOnspeechchange(String onspeechchange) {
getStateHelper().put(PropertyKeys.onspeechchange, onspeechchange);
}
public String getPlaceholder() {
return (String) getStateHelper().eval(PropertyKeys.placeholder, "Enter a Search Term");
}
public void setPlaceholder(String placeholder) {
getStateHelper().put(PropertyKeys.placeholder, placeholder);
}
}
Tenga en cuenta que los captadores tienen todos los valores por defecto especificados. Si el eval()
devuelve null
, se devolverá el valor predeterminado. También he neutralizado los nombres de los atributos de alguna manera para que puedan ser reutilizados para futuros navegadores que no sean webkit simplemente modificando el renderizador en consecuencia.
Y así es como el SiteSearchRenderer
procesador debe ser similar para el componente anterior:
@FacesRenderer(
componentFamily=SiteSearch.COMPONENT_FAMILY,
rendererType=SiteSearchRenderer.RENDERER_TYPE
)
public class SiteSearchRenderer extends AutoCompleteRenderer {
public static final String RENDERER_TYPE = "com.example.SiteSearchRenderer";
@Override
protected void renderPassThruAttributes(FacesContext facesContext, UIComponent component, String[] attrs) throws IOException {
ResponseWriter writer = facesContext.getResponseWriter();
writer.writeAttribute("x-webkit-speech", "x-webkit-speech", null);
writer.writeAttribute("x-webkit-grammar", component.getAttributes().get("grammar"), "grammar");
writer.writeAttribute("onwebkitspeechchange", component.getAttributes().get("onspeechchange"), "onspeechchange");
writer.writeAttribute("placeholder", component.getAttributes().get("placeholder"), "placeholder");
super.renderPassThruAttributes(facesContext, component, attrs);
}
}
para usarlo en la vista, que, por supuesto, hay que registrarlo como una etiqueta. Crear un archivo /WEB-INF/my.taglib.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<facelet-taglib
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd"
version="2.0"
>
<namespace>http://example.com/ui</namespace>
<tag>
<tag-name>siteSearch</tag-name>
<component>
<component-type>com.example.SiteSearch</component-type>
<renderer-type>com.example.SiteSearchRenderer</renderer-type>
</component>
</tag>
</facelet-taglib>
Tenga en cuenta que no es necesario un <renderer>
en faces-config.xml
para esto. La anotación @FacesRenderer
puede hacer su trabajo en componentes personalizados reales.Por lo tanto, elimine la entrada <renderer>
en faces-config.xml
que creó en función de su pregunta anterior.
ahora a JSF que usted tiene una taglib a medida por el siguiente parámetro contexto en web.xml
:
<context-param>
<param-name>javax.faces.FACELETS_LIBRARIES</param-name>
<param-value>/WEB-INF/my.taglib.xml</param-value>
</context-param>
Finalmente, puede utilizarlo como sigue:
<html ... xmlns:my="http://example.com/ui">
...
<my:siteSearch />
incluso puede especificar adicional atributos que anularán los valores predeterminados establecidos en el componente:
<my:siteSearch grammar="builtin:language" onspeechchange="alert('peek-a-boo')" placeholder="Search" />
Para IDE autocompletar en atributos, necesitaría especificar cada uno como un <attribute>
por separado en la declaración <tag>
en el my.taglib.xml
.
@BalusC alguna idea? – Adam
Estaba viendo series (House MD en este momento). Ten un poco de paciencia :) – BalusC
Haha. No problemas. Creo que cada vez que veo una pregunta de JSF, automáticamente asumo que la tuya será la respuesta sin siquiera mirar. ¿Alguien puede decir ninja JSF? – Adam