Wenn Sie eine bestimmte Komponente benötigen, die einen anderen Renderer als <p:autoComplete>
verwendet, können Sie nicht wirklich eine benutzerdefinierte Komponente mit einer eigenen Familie und einem eigenen Komponententyp erstellen. Sie können die PrimeFaces AutoComplete
(und ihren Renderer) immer noch erweitern, um einige Codebeispiele zu speichern.
In der benutzerdefinierten Komponente müssen Getter für diese Attribute bereitgestellt werden. Sie können ebenso gut Setter angeben. Auf diese Weise können Sie die Standardwerte auf der Sichtseite immer überschreiben. Diese Getter/Setter sollten wiederum an StateHelper
delegieren.
Es gibt nur ein kleines Problem mit x-webkit-*
Attributen. Die ist ein ungültiges Zeichen in Java-Bezeichnern. Daher müssen Sie die Getter/Setter umbenennen und den Renderer etwas ändern, da der Standard-Renderer davon abhängig ist, dass der Name der Komponenteneigenschaft genau dem Namen des Tag-Attributs entspricht. Update: Ich verstehe, dass x-webkit-speech
nur so gerendert werden soll (so, kein Getter/Setter notwendig) und dass x-webkit-grammer
eigentlich ein Tippfehler ist, sollte es x-webkit-grammar
sein.
Hier ist, wie die SiteSearch
Komponente aussehen kann:
@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);
}
}
Bitte beachten Sie, dass die Getter alle Standardwerte angegeben haben. Wenn eval()
null
zurückgibt, wird stattdessen der Standardwert zurückgegeben. Ich habe auch die Attributnamen etwas neutralisiert, so dass sie für zukünftige Browser ohne Webkit wiederverwendet werden können, indem ich den Renderer entsprechend modifiziere.
Und hier ist, wie die SiteSearchRenderer
Renderer wie für die obige Komponente aussehen sollen:
@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);
}
}
Um es in der Ansicht zu verwenden, wir brauchen natürlich es als Tag zu registrieren. Erstellen Sie eine Datei /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>
Beachten Sie, dass Sie keine <renderer>
in faces-config.xml
dafür mehr benötigen. Die @FacesRenderer
Annotation kann einfach ihre Arbeit an echten benutzerdefinierten Komponenten erledigen.Entfernen Sie also den <renderer>
Eintrag in faces-config.xml
, den Sie basierend auf Ihrer vorherigen Frage erstellt haben.
Jetzt JSF sagen, dass Sie eine benutzerdefinierte taglib durch den folgenden Zusammenhang param in web.xml
haben:
<context-param>
<param-name>javax.faces.FACELETS_LIBRARIES</param-name>
<param-value>/WEB-INF/my.taglib.xml</param-value>
</context-param>
Schließlich können Sie es wie folgt verwendet werden:
<html ... xmlns:my="http://example.com/ui">
...
<my:siteSearch />
Sie können sogar angeben, zusätzliche Attribute, die die in der Komponente festgelegten Voreinstellungen überschreiben:
<my:siteSearch grammar="builtin:language" onspeechchange="alert('peek-a-boo')" placeholder="Search" />
Für die automatische Vervollständigung der IDE in Attributen müssen Sie alle als separate <attribute>
in der <tag>
Deklaration in my.taglib.xml
angeben.
@BalusC irgendwelche Ideen? – Adam
War gerade Serie (House MD gerade). Hab ein bisschen Geduld :) – BalusC
Haha. Keine Probleme. Ich denke immer, wenn ich eine JSF Frage sehe, nehme ich einfach automatisch an, dass deine Antwort die Antwort sein wird, ohne überhaupt nachzusehen. Kann jemand JSF Ninja sagen? – Adam