Nếu bạn cần một thành phần cụ thể sử dụng trình kết xuất khác hơn <p:autoComplete>
thì bạn thực sự không thể tạo một thành phần tùy chỉnh với loại thành phần và gia đình riêng của nó. Bạn vẫn có thể mở rộng PrimeFaces AutoComplete
(và trình kết xuất đồ họa) của nó để lưu một số mã soạn sẵn.
Trong thành phần tùy chỉnh, bạn cần cung cấp getters cho các thuộc tính đó. Bạn cũng có thể chỉ định các bộ định cư, bằng cách này bạn luôn có thể ghi đè các giá trị mặc định từ phía bên xem. Những getters/setters này sẽ lần lượt ủy quyền cho StateHelper
.
Chỉ có một vấn đề nhỏ với thuộc tính x-webkit-*
. -
là ký tự không hợp lệ trong số nhận dạng Java. Vì vậy, bạn phải đổi tên getters/setters và thay đổi renderer phần nào như là renderer tiêu chuẩn dựa trên tên thuộc tính thành phần được chính xác giống như tên thuộc tính thẻ. Cập nhật: Tôi hiểu rằng x-webkit-speech
chỉ nên được hiển thị như vậy (vì vậy, không cần thiết phải trả tiền/setter) và x-webkit-grammer
thực sự là lỗi đánh máy, nó phải là x-webkit-grammar
.
Đây là cách các thành phần SiteSearch
thể trông giống như:
@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);
}
}
Xin lưu ý rằng thu khí có tất cả các giá trị mặc định theo quy định. Nếu số eval()
trả về null
, thì giá trị mặc định sẽ được trả lại thay thế. Tôi cũng đã vô hiệu hóa các tên thuộc tính phần nào để nó có thể được tái sử dụng cho bất kỳ trình duyệt không phải webkit nào trong tương lai bằng cách chỉ sửa đổi trình kết xuất phù hợp.
Và dưới đây là cách các SiteSearchRenderer
renderer sẽ giống như đối với các thành phần trên:
@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);
}
}
Để sử dụng nó trong giao diện, chúng tôi tất nhiên cần phải đăng ký nó như là một thẻ. Tạo một 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>
Lưu ý rằng bạn không cần một <renderer>
trong faces-config.xml
cho điều này nữa. Chú thích @FacesRenderer
chỉ có thể thực hiện công việc của mình trên các thành phần tùy chỉnh thực.Vì vậy, hãy xóa mục nhập <renderer>
trong faces-config.xml
mà bạn đã tạo dựa trên câu hỏi trước đó của mình.
Giờ thì nói cho JSF rằng bạn đã có một taglib tùy chỉnh bằng các param bối cảnh sau trong web.xml
:
<context-param>
<param-name>javax.faces.FACELETS_LIBRARIES</param-name>
<param-value>/WEB-INF/my.taglib.xml</param-value>
</context-param>
Cuối cùng bạn có thể sử dụng nó như sau:
<html ... xmlns:my="http://example.com/ui">
...
<my:siteSearch />
Bạn thậm chí có thể chỉ định thêm các thuộc tính sẽ ghi đè các giá trị mặc định được đặt trong thành phần:
<my:siteSearch grammar="builtin:language" onspeechchange="alert('peek-a-boo')" placeholder="Search" />
Để tự động hoàn thành IDE trên các thuộc tính, bạn cần phải chỉ định từng thuộc tính riêng lẻ <attribute>
trong khai báo <tag>
trong my.taglib.xml
.
@BalusC bất kỳ ý tưởng nào? – Adam
Đã xem chuỗi video (House MD ngay bây giờ). Có một chút kiên nhẫn :) – BalusC
Haha. Không vấn đề gì. Tôi nghĩ bất cứ khi nào tôi nhìn thấy một câu hỏi JSF tôi chỉ tự động giả định của bạn sẽ là câu trả lời mà không cần nhìn. Có ai nói JSF ninja không? – Adam