2010-07-28 10 views

Odpowiedz

19

Niestety, nie jest to możliwe w standardowej implementacji JSF. Składnik i mechanizm renderujący oficjalnie nie obsługują tego atrybutu. Możesz jednak wygenerować renderera, który to obsługuje.

Ponieważ jest to dość powszechny wymóg/życzenie, pomyślałem, aby rzucić okiem na to, co jest możliwe.

Najpierw niektóre informacje dodatkowe: JSF domyślnie używa ResponseWriter#writeText(), aby zapisać treść znacznika, która domyślnie wymyka się HTML. Chcielibyśmy pozwolić, aby używał on ResponseWriter#write() zamiast jak z <h:outputText escape="false" />. Chcielibyśmy rozszerzyć standard MessagesRenderer standardowej implementacji JSF i zastąpić odpowiednio metodę encodeEnd(). Ale ponieważ MessagesRenderer#encodeEnd() zawiera dość dużo kodu (~ 180 linii), który wolimy nie kopiować, aby zmienić jedną lub dwie linie, uważam, że lepiej zastąpić ResponseWriter niestandardową implementacją przy pomocy ResponseWriterWrapper, gdzie writeText() został zastąpiony, aby obsłużyć ucieczkę.

Więc skończyło się z tym:

package com.example; 

import java.io.IOException; 

import javax.faces.component.UIComponent; 
import javax.faces.context.FacesContext; 
import javax.faces.context.ResponseWriter; 
import javax.faces.context.ResponseWriterWrapper; 
import javax.faces.render.FacesRenderer; 

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

@FacesRenderer(componentFamily="javax.faces.Messages", rendererType="javax.faces.Messages") 
public class EscapableMessagesRenderer extends MessagesRenderer { 

    @Override 
    public void encodeEnd(FacesContext context, UIComponent component) throws IOException { 
     final ResponseWriter originalResponseWriter = context.getResponseWriter(); 

     try { 
      context.setResponseWriter(new ResponseWriterWrapper() { 

       @Override 
       public ResponseWriter getWrapped() { 
        return originalResponseWriter; 
       } 

       @Override 
       public void writeText(Object text, UIComponent component, String property) throws IOException { 
        String string = String.valueOf(text); 
        String escape = (String) component.getAttributes().get("escape"); 
        if (escape != null && !Boolean.valueOf(escape)) { 
         super.write(string); 
        } else { 
         super.writeText(string, component, property); 
        } 
       } 
      }); 

      super.encodeEnd(context, component); // Now, render it! 
     } finally { 
      context.setResponseWriter(originalResponseWriter); // Restore original writer. 
     } 
    } 
} 

Pomimo @FacesRenderer adnotacją, że się nadpisane przez domyślny MessagesRenderer realizacji. Podejrzewam tu błąd, więc zgłosiłem issue 1748. Aby dostać to i tak pracować, musimy spaść z powrotem do faces-config.xml:

<render-kit> 
    <renderer> 
     <component-family>javax.faces.Messages</component-family> 
     <renderer-type>javax.faces.Messages</renderer-type> 
     <renderer-class>com.example.EscapableMessagesRenderer</renderer-class> 
    </renderer> 
</render-kit> 

Następnie, aby go wywołać, po prostu zrobić:

<h:messages escape="false" /> 

I to działa! :)


Uwaga: powyższe wpływa <h:messages> tylko. Aby zrobić to samo dla <h:message>, zrób to samo, ale zamień w dowolnym miejscu"Messages" przez "Message" (rodzina komponentów, typ renderera i nazwy klas).

+0

Dzięki BalusC, przyjechałem do tego samego rozwiązania również dzisiaj (i złożyłem ten sam błąd https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=1750) Użyłem wzorca dla delegata mój autor odpowiedzi, ale myślę, że wolę to, co zrobiłeś z opakowaniem. Dzięki! –

+0

Nowy link do zgłaszanego problemu: http://java.net/jira/browse/JAVASERVERFACES-1750 –

+0

działa idealnie BalusC, dziękuję! –

1

Potrzebna jest określona liczba escape="false" dostarczona przez OmniFaces <o:messages> component. Biblioteka narzędzi OmniFaces jest dostępna dla JSF 2.

Wysłałem to rozwiązanie wspomniane przez komentarz @ BalusC jako odpowiedź, ponieważ jest to najbardziej proste rozwiązanie.

Powiązane problemy