Jeśli potrzebujesz konkretnego komponentu, który używa innego renderera niż <p:autoComplete>
, to naprawdę nie możesz obejść tworzenia niestandardowego komponentu z własną rodziną i typem komponentu. Nadal można po prostu rozszerzyć PrimeFaces AutoComplete
(i jego renderer), aby zapisać jakiś kod na płycie głównej.
W komponencie niestandardowym należy podać metodę pobierającą dla tych atrybutów. Możesz równie dobrze określić setery, w ten sposób zawsze możesz zastąpić wartości domyślne od strony widoku. Te podmioty pobierające/ustawiające powinny z kolei delegować na StateHelper
.
Jest tylko mały problem z atrybutami x-webkit-*
. -
jest niedozwolonym znakiem w identyfikatorach Java. Musisz więc zmienić nazwy modułów pobierających/ustawiających i zmienić renderer, ponieważ standardowy renderer opiera się na nazwie właściwości komponentu, która jest dokładnie taka sama, jak nazwa atrybutu tagu. Aktualizacja: Rozumiem, że x-webkit-speech
powinien być renderowany w niezmienionej formie (więc nie jest konieczny żaden program pobierający/ustawiający), a to, że x-webkit-grammer
jest w rzeczywistości literówką, powinno być x-webkit-grammar
.
Oto jak składnik SiteSearch
może wyglądać następująco:
@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);
}
}
Należy pamiętać, że w pozyskiwaniu wszystkie wartości domyślne określone. Jeśli eval()
zwraca null
, zamiast tego zostanie zwrócona wartość domyślna. Zneutralizowałem też nieco nazwy atrybutów, aby można je było ponownie wykorzystać w przyszłych przeglądarkach innych niż webkit, modyfikując odpowiednio renderer.
A oto jak SiteSearchRenderer
renderujący powinien wyglądać dla powyższego składnika:
@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);
}
}
Aby użyć go w widoku, my oczywiście trzeba zarejestrować go jako znak. Tworzenie /WEB-INF/my.taglib.xml
plik:
<?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>
pamiętać, że nie potrzebują <renderer>
w faces-config.xml
za to więcej. Adnotacja @FacesRenderer
może po prostu wykonać swoje zadanie na prawdziwych niestandardowych komponentach.Usuń więc wpis <renderer>
z faces-config.xml
utworzony na podstawie poprzedniego pytania.
teraz powiedzieć JSF, że masz niestandardowy TagLib według poniższego param kontekstowego w web.xml
:
<context-param>
<param-name>javax.faces.FACELETS_LIBRARIES</param-name>
<param-value>/WEB-INF/my.taglib.xml</param-value>
</context-param>
Wreszcie można go używać w następujący sposób:
<html ... xmlns:my="http://example.com/ui">
...
<my:siteSearch />
Można nawet określić dodatkowe atrybuty, które zastąpią ustawienia domyślne w komponencie:
<my:siteSearch grammar="builtin:language" onspeechchange="alert('peek-a-boo')" placeholder="Search" />
W przypadku autouzupełniania IDE w atrybutach należy podać każdą z nich jako oddzielną <attribute>
w deklaracji w dokumencie .
@BalusC jakieś pomysły? – Adam
Oglądałem serię (House MD teraz). Trochę cierpliwości :) – BalusC
Haha. Nie problemy. Wydaje mi się, że za każdym razem, gdy widzę pytanie o JSF, automatycznie zakładam, że twoja odpowiedź stanie się bezowocna. Czy ktoś może powiedzieć ninja JSF? – Adam