Giải pháp mà tôi tìm thấy là mở rộng và triển khai lại các phương thức encodeMarkup cho trình kết xuất đồ họa. Tôi muốn có một giải pháp tổng quát hơn, nhưng sau khi nhìn vào mã nguồn của Primefaces, tôi không thấy bất kỳ móc chung nào cho các trình kết xuất thành phần để thêm các thuộc tính tùy chỉnh. Đánh dấu được viết ra theo phương pháp encodeMarkup(FacesContext context, InputText inputText)
của trình kết xuất đồ họa. Nó gọi hệ thống phân cấp lớp thành renderPassThruAttributes(FacesContext context, UIComponent component, String[] attributes)
nhưng nó chỉ cấp dữ liệu trong các chuỗi String [] cuối cùng tĩnh từ org.primefaces.util.HTML
.
Trong trường hợp của tôi, tôi muốn hỗ trợ cho thuộc tính 'tự động lấy nét' trên các thành phần InputMask, InputText, InputTextarea và Password. Hơn nữa, việc triển khai thực hiện tương tự cho từng thành phần, vì vậy tôi sẽ hướng dẫn thực hiện 'lấy nét tự động' trên thành phần InputText, nhưng rõ ràng nó có thể được mở rộng như thế nào để hỗ trợ nhiều thuộc tính hơn và nhiều thành phần hơn.
Để mở rộng/ghi đè trình kết xuất, bạn sẽ cần có sẵn nguồn Primefaces và tìm phương thức encodeMarkup và sao chép nội dung của nó. Dưới đây là ví dụ cho InputTextRenderer:
protected void encodeMarkup(FacesContext context, InputText inputText) throws IOException {
ResponseWriter writer = context.getResponseWriter();
String clientId = inputText.getClientId(context);
writer.startElement("input", null);
writer.writeAttribute("id", clientId, null);
writer.writeAttribute("name", clientId, null);
writer.writeAttribute("type", inputText.getType(), null);
String valueToRender = ComponentUtils.getValueToRender(context, inputText);
if(valueToRender != null) {
writer.writeAttribute("value", valueToRender , null);
}
renderPassThruAttributes(context, inputText, HTML.INPUT_TEXT_ATTRS);
if(inputText.isDisabled()) writer.writeAttribute("disabled", "disabled", null);
if(inputText.isReadonly()) writer.writeAttribute("readonly", "readonly", null);
if(inputText.getStyle() != null) writer.writeAttribute("style", inputText.getStyle(), null);
writer.writeAttribute("class", createStyleClass(inputText), "styleClass");
writer.endElement("input");
}
Mở rộng/Trọng renderer với riêng bạn (xem ý kiến cho mã quan trọng):
public class HTML5InputTextRenderer extends InputTextRenderer {
Logger log = Logger.getLogger(HTML5InputTextRenderer.class);
//Define your attributes to support here
private static final String[] html5_attributes = { "autofocus" };
protected void encodeMarkup(FacesContext context, InputText inputText) throws IOException {
ResponseWriter writer = context.getResponseWriter();
String clientId = inputText.getClientId(context);
writer.startElement("input", null);
writer.writeAttribute("id", clientId, null);
writer.writeAttribute("name", clientId, null);
writer.writeAttribute("type", inputText.getType(), null);
String valueToRender = ComponentUtils.getValueToRender(context, inputText);
if (valueToRender != null) {
writer.writeAttribute("value", valueToRender, null);
}
renderPassThruAttributes(context, inputText, HTML.INPUT_TEXT_ATTRS);
//Make an extra call to renderPassThruAttributes with your own attributes array
renderPassThruAttributes(context, inputText, html5_attributes);
if (inputText.isDisabled())
writer.writeAttribute("disabled", "disabled", null);
if (inputText.isReadonly())
writer.writeAttribute("readonly", "readonly", null);
if (inputText.getStyle() != null)
writer.writeAttribute("style", inputText.getStyle(), null);
writer.writeAttribute("class", createStyleClass(inputText), "styleClass");
writer.endElement("input");
}
}
Cấu hình ghi đè đang hiển thị trong faces-config.xml
<?xml version='1.0' encoding='UTF-8'?>
<faces-config 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-facesconfig_2_0.xsd"
version="2.0">
<!-- snip... -->
<render-kit>
<renderer>
<component-family>org.primefaces.component</component-family>
<renderer-type>org.primefaces.component.InputTextRenderer</renderer-type>
<renderer-class>com.mycompany.HTML5InputTextRenderer</renderer-class>
</renderer>
</render-kit>
<!-- snip... -->
</faces-config>
và chỉ trong trường hợp nếu bạn không có cấu hình khuôn mặt được định cấu hình trong web.xml của mình thêm:
<context-param>
<param-name>javax.faces.CONFIG_FILES</param-name>
<param-value>
/WEB-INF/faces-config.xml, /faces-config.xml
</param-value>
</context-param>
Sau đó sử dụng điều này trong một số lập trình:
<p:inputText id="activateUserName" value="${someBean.userName}"
autofocus="on">
</p:inputText>
Lưu ý: JSF là không hài lòng với các thuộc tính mà không có giá trị. Trong khi tự động lấy nét trong HTML5 không sử dụng một giá trị, JSF sẽ ném một lỗi nếu không được cung cấp, vì vậy hãy chắc chắn xác định một số giá trị ném đi khi thêm các thuộc tính đó.
Tuyệt vời, điều này trông đẹp hơn nhiều so với giải pháp cho mỗi thành phần. Tôi chắc chắn các trường hợp sử dụng cụ thể có thể tạo ra các đối số theo cách nào đó. Nếu tôi nhận được thời gian tôi sẽ cố gắng này ra vì có vẻ như nó sẽ là nhanh hơn nhiều so với homegrowing tất cả các thành phần. – Rich
UIComponent # getCurrentComponent (FacesContext) có vẻ là chữ ký, vì vậy trong ngữ cảnh của phương thức startElement không có sẵn. Tôi thấy trong Omnifaces của bạn cam kết bạn sử dụng Components.getCurrentCompnent() mà không yêu cầu bối cảnh, mặc dù đó là một lớp OmniFaces mà không có sẵn chỉ trong PrimeFaces. Tại thời điểm đó Nó sẽ nguy hiểm hơn đối với tôi để cũng phải ghi đè lên bất kỳ thành phần nào có thể truyền null đến startElement. Bạn có đề nghị tôi kéo OmniFaces hoặc có cách nào khác không? – Rich
Mẫu 'Components # getCurrentComponent()' Các OmniFaces chỉ đại biểu cho 'UIComponent # getCurrentComponent()'. Bạn không rõ ràng nếu bạn đã thử nghiệm nó hay không, nhưng nó làm việc cho tôi. – BalusC