2011-07-28 12 views
11

Próbuję napisać mechanizm renderujący, który przetworzy atrybut placeholder na składniku <h:inputText>. Udałem się na tę ścieżkę po przeczytaniu JSF 2.0 strips out needed HTML5 attributes i wydaje się poprawne. Oto mój niestandardowy mechanizm renderującyDodawanie obsługi atrybutów niestandardowych (HTML5) do składnika JSF 2.0 UIInput

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); 
    } 
} 

I to renderer jest zarejestrowany w twarze config jak

<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> 

ten zostanie zarejestrowany w porządku, nie ma problemów.

Moim zamiarem jest przetworzenie atrybutu placeholder, wstawienie go, a następnie przekazanie przetwarzania do super. Powyższy kod nie działa, ponieważ wstawiam atrybut w niewłaściwym miejscu. Musi zostać wstawiony po wykonaniu writer.startElement('input'). Jednak startElement musi się odbywać gdzieś w metodzie super-super-encodeBegin(). Więc jak wstawić niestandardowy atrybut ("symbol zastępczy" w tym przypadku), a następnie kontynuować przepływ wykonywania?

NB: Powyższy kod dodaje atrybut placeholder, ale nie odnosi się do komponentu wejściowego, który zamierzam, Zapisuje go do elementu nadrzędnego wpisu (ponieważ próbuję wpisać atrybut, zanim sam komponent zostanie faktycznie użyty zapisany w strumieniu, stosuje atrybut do bieżącego komponentu)

Odpowiedz

19

To jest moja droga. Dodałem atrybuty zastępcze i atrybuty danych. Jeśli chcesz dodać więcej atrybutów, powinieneś po prostu dodać jego nazwę do tablicy atrybutów.

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); 

    } 

} 

Powinieneś dodać to do pliku 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

Jest to zdecydowanie najbardziej praktyczna i najlepsza odpowiedź! :) – Nikhil

+1

Dzięki za odpowiedź i chociaż jest to rzetelna odpowiedź, kod ma błąd. Zwrot get (atrybut) jest obiektem, który może być wartością logiczną (należy na przykład uwzględnić atrybut "required"). Usuń całkowicie (String) i ustaw typ powrotu jako Object. –

+1

Należy zauważyć, że to nie działa z '' rodzicem z '' dziećmi. JSF umieszcza atrybut 'required' w elemencie' 'zamiast' '. Czy powiedziałem, że kocham JSF? –

6

Można po prostu przesłonić metodę startElement ResponseWoice, ta metoda jest wywoływana tylko raz, a następnie można przywrócić oryginalny obiekt odpowiedzi.

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

Powyższy działa lepiej (choć brakuje niektórych importu, poprawiłam getWrapped() jak w JSF 1.2 jest już publiczna, itp). Myślę, że to najlepsza odpowiedź. Prawdopodobnie lepiej jest też użyć, jeśli ("stała" .equals (wartość)), która obsługuje zerową kontrolę, ponieważ stała nigdy nie będzie równa zeru, ale nie spowoduje NPE. Oficjalnie gardzę splotem JSF jako lepszej alternatywy, ale doceniam wszystkie dobre opinie tutaj (dzięki Joelowi za wsparcie StackOverflow). –

2

I przesłonić dla 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

Dla tych, którzy czytają zbyt szybko, potrzebujesz również znacznika z góry w swoim plik faces-config.xml. –

Powiązane problemy