Se è necessario un componente specifico che utilizza un renderer diverso da <p:autoComplete>
, non è possibile aggirare la creazione di un componente personalizzato con la propria famiglia e il tipo di componente. È ancora possibile estendere PrimeFaces AutoComplete
(e il suo renderer) per salvare qualche codice boilerplate.
Nel componente personalizzato, è necessario fornire getter per tali attributi. Puoi anche specificare setter, in questo modo puoi sempre ignorare i valori predefiniti dal lato vista. Questi getter/setter dovrebbero a loro volta delegare a StateHelper
.
C'è solo un piccolo problema con gli attributi x-webkit-*
. -
è un carattere non valido negli identificatori Java. Pertanto, è necessario rinominare i getter/setter e modificare il renderer in qualche modo poiché il renderer standard si basa sul nome della proprietà del componente esattamente uguale al nome dell'attributo del tag. Aggiornamento: ho capito che x-webkit-speech
deve essere visualizzato come è (quindi, nessun getter/setter necessario) e che x-webkit-grammer
è in realtà un errore di battitura, dovrebbe essere x-webkit-grammar
.
Ecco come la componente SiteSearch
può apparire come:
@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);
}
}
Si prega di notare che i getter hanno tutti i valori predefiniti specificati. Se eval()
restituisce null
, verrà restituito il valore predefinito. Ho anche neutralizzato un po 'i nomi degli attributi in modo che possano essere riutilizzati per qualsiasi futuro browser non Webkit semplicemente modificando il renderer di conseguenza.
Ed ecco come il renderer SiteSearchRenderer
dovrebbe essere simile per la componente di cui sopra:
@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);
}
}
di utilizzarlo in vista, abbiamo naturalmente bisogno di registrarlo come un tag. Creare un file /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>
Si noti che non è necessario un <renderer>
in faces-config.xml
per questo più. L'annotazione @FacesRenderer
può fare il proprio lavoro solo su componenti personalizzati reali.Quindi rimuovi la voce faces-config.xml
che hai creato in base alla tua domanda precedente.
Ora dirà JSF che hai un taglib personalizzato dal seguente contesto param in web.xml
:
<context-param>
<param-name>javax.faces.FACELETS_LIBRARIES</param-name>
<param-value>/WEB-INF/my.taglib.xml</param-value>
</context-param>
Infine è possibile utilizzarlo come segue:
<html ... xmlns:my="http://example.com/ui">
...
<my:siteSearch />
Si può anche specificare ulteriori attributi che sovrascrivono i valori predefiniti impostati nel componente:
<my:siteSearch grammar="builtin:language" onspeechchange="alert('peek-a-boo')" placeholder="Search" />
Per il completamento automatico IDE sugli attributi, è necessario specificarne uno come numero separato nella dichiarazione <tag>
nello my.taglib.xml
.
@BalusC qualche idea? – Adam
Stavo guardando serie (House MD in questo momento). Abbi un po 'di pazienza :) – BalusC
Haha. Non problemi Penso che ogni volta che vedo una domanda JSF automaticamente presumo che la tua sarà la risposta senza nemmeno guardare. Qualcuno può dire JSF ninja? – Adam