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).
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! –
Nowy link do zgłaszanego problemu: http://java.net/jira/browse/JAVASERVERFACES-1750 –
działa idealnie BalusC, dziękuję! –