2011-07-28 26 views
11

Tôi đang cố gắng viết trình kết xuất xử lý thuộc tính placeholder trên thành phần <h:inputText>. Tôi đi đến con đường này sau khi đọc JSF 2.0 strips out needed HTML5 attributes và có vẻ như chính xác. Dưới đây là tùy chỉnh của tôi rendererThêm hỗ trợ thuộc tính tùy chỉnh (HTML5) vào thành phần UIInput JSF 2.0

public class InputRenderer extends com.sun.faces.renderkit.html_basic.TextRenderer{ 

    @Override 
    public void encodeBegin(FacesContext context, UIComponent component) 
    throws IOException { 
     System.out.println("Rendering :"+component.getClientId()); 

     String placeholder = (String)component.getAttributes().get("placeholder"); 
     if(placeholder != null) { 
      ResponseWriter writer = context.getResponseWriter(); 
      writer.writeAttribute("placeholder", placeholder, "placeholder"); 
     } 

     super.encodeBegin(context, component); 

    } 


    @Override 
    public void decode(FacesContext context, UIComponent component) { 
     super.decode(context, component); 
    } 

    @Override 
    public void encodeEnd(FacesContext context, UIComponent component) 
    throws IOException { 
     super.encodeEnd(context, component); 
    } 
} 

Và renderer này được đăng ký trong khuôn mặt cấu hình như

<render-kit> 
    <renderer> 
     <component-family>javax.faces.Input</component-family> 
     <renderer-type>javax.faces.Text</renderer-type> 
     <renderer-class>com.example.renderer.InputRenderer</renderer-class> 
    </renderer> 
</render-kit> 

này được đăng ký tốt, không có vấn đề đó.

Mục đích của tôi là xử lý thuộc tính placeholder, chèn thuộc tính đó, và sau đó ủy quyền xử lý thành siêu. Mã trên của tôi không hoạt động vì tôi đang chèn thuộc tính ở vị trí sai. Nó phải được chèn sau khi writer.startElement('input') đã được thực hiện. Tuy nhiên, startElement phải xảy ra ở đâu đó trong phương thức encodeBegin() của siêu. Vậy làm cách nào để chèn thuộc tính tùy chỉnh ('trình giữ chỗ' trong trường hợp này) và sau đó tiếp tục luồng thực thi?

NB: Đoạn mã trên không thêm thuộc tính placeholder nhưng không ghi vào thành phần đầu vào mà tôi dự định, nó viết nó cho cha mẹ của đầu vào (vì tôi đang cố gắng viết thuộc tính trước khi thành phần đó thực sự là được viết trong luồng, nó áp dụng thuộc tính cho thành phần hiện tại)

Trả lời

19

Đây là cách của tôi. Tôi đã thêm các thuộc tính giữ chỗ và dữ liệu chủ đề. Nếu bạn muốn thêm các thuộc tính khác, bạn chỉ cần thêm tên của nó vào mảng thuộc tính.

import javax.faces.component.UIComponent; 
import javax.faces.context.FacesContext; 
import javax.faces.context.ResponseWriter; 

import com.sun.faces.renderkit.html_basic.TextRenderer; 

public class InputRender extends TextRenderer { 

    @Override 
    protected void getEndTextToRender(FacesContext context, 
      UIComponent component, 
      String currentValue) 
    throws java.io.IOException{ 

     String [] attributes = {"placeholder","data-theme"}; 

     ResponseWriter writer = context.getResponseWriter(); 

     for(String attribute : attributes) 
     { 
      String value = (String)component.getAttributes().get(attribute); 
      if(value != null) {        
       writer.writeAttribute(attribute, value, attribute); 
      } 
     } 

     super.getEndTextToRender(context, component, currentValue); 

    } 

} 

Bạn nên thêm tệp này vào tệp faces-config.xml.

<render-kit> 
    <renderer> 
     <component-family>javax.faces.Input</component-family> 
     <renderer-type>javax.faces.Text</renderer-type> 
     <renderer-class>your.package.InputRenderer</renderer-class> 
    </renderer> 
</render-kit> 
+0

Đây là câu trả lời thực tế nhất và tốt nhất! :) – Nikhil

+1

Cảm ơn bạn đã phản hồi và trong khi đây là câu trả lời hợp lý, mã có lỗi. Sự trở lại của get (attribute) là một đối tượng, có thể là một Boolean (xem xét thuộc tính 'required'). Loại bỏ toàn bộ chuỗi (String) và thiết lập kiểu trả về là Object. –

+1

Lưu ý rằng điều này không hoạt động với '' cha mẹ với '' con. JSF đặt thuộc tính 'required' vào phần tử' 'thay vì phần tử' '. Tôi có nói rằng tôi yêu JSF không? –

6

Bạn chỉ có thể ghi đè phương thức startWriters startElement, phương thức đó chỉ được gọi một lần và sau đó bạn có thể khôi phục đối tượng responsewriter gốc.

import javax.faces.context.*; 
import java.io.IOException; 

public class InputRenderer extends com.sun.faces.renderkit.html_basic.TextRenderer{ 

     // Put all of the attributes you want to render here... 
     private static final String[] ATTRIBUTES = {"required","placeholder"}; 

    @Override 
    protected void getEndTextToRender(FacesContext context, 
      UIComponent component, String currentValue) throws IOException { 
     final ResponseWriter originalResponseWriter = context.getResponseWriter(); 
     context.setResponseWriter(new ResponseWriterWrapper() { 

      @Override 
// As of JSF 1.2 this method is now public. 
      public ResponseWriter getWrapped() { 
       return originalResponseWriter; 
      } 

      @Override 
      public void startElement(String name, UIComponent component) 
        throws IOException { 
       super.startElement(name, component); 
if ("input".equals(name)) { 
    for (String attribute : ATTRIBUTES) 
    { 
    Object value = component.getAttributes().get(attribute); 
    if (value != null) 
    { 
     super.writeAttribute(attribute,value,attribute); 
} 
    } 
} 
     }); 
     super.getEndTextToRender(context, component, currentValue); 
     context.setResponseWriter(originalResponseWriter); // Restore original writer. 
    } 



} 
+0

Trên đây hoạt động tốt hơn (mặc dù thiếu một số hàng nhập khẩu, tôi sửa chữa getWrapped() như trong JSF 1.2 hiện công khai, vv). Tôi nghĩ đây là câu trả lời hay nhất. Nó cũng có lẽ là tốt hơn để sử dụng nếu ("hằng số". Equals (giá trị)) như là xử lý null-kiểm tra như là hằng số sẽ không bao giờ bằng null nhưng sẽ không ném một NPE. Tôi bây giờ chính thức coi thường sự chuyển dịch của JSF như là một lựa chọn tốt hơn bằng cách nào đó nhưng đánh giá cao tất cả các thông tin phản hồi tốt ở đây (nhờ Joel để ủng hộ StackOverflow). –

2

Và để ghi đè cho MyFaces 2.0.8+

package com.hsop.abc.eld; 

import java.io.IOException; 

import javax.faces.component.UIComponent; 
import javax.faces.context.FacesContext; 
import javax.faces.context.ResponseWriter; 

import org.apache.myfaces.renderkit.html.HtmlTextRenderer; 

public class InputRenderer extends HtmlTextRenderer 
{ 
    @Override 
    protected void renderInputBegin(FacesContext context, UIComponent component) 
      throws IOException 
    { 
     // TODO Auto-generated method stub 
     super.renderInputBegin(context, component); 

    Object placeholder = component.getAttributes().get("placeholder"); 
    if(placeholder != null) { 
     ResponseWriter writer = context.getResponseWriter(); 
     writer.writeAttribute("placeholder", placeholder, "placeholder"); 
    } 

    } 
} 
+0

Đối với những người đọc quá nhanh, bạn cũng cần thẻ từ trên tệp faces-config.xml. –

Các vấn đề liên quan