showcases - templates jsf primefaces
Incrustar un enlace(u otro html) en un mensaje JSF (2)
Quiero insertar un enlace en un mensaje JSF, ¿es esto posible?
Cuando lo intento, el html representado de la etiqueta h: messages escapa de los caracteres html. Intenté configurar el atributo de escape de la etiqueta h: messages en falso, pero eso no ayudó.
El atributo de escape="false"
que necesita es proporcionado por el componente OmniFaces <o:messages>
. La biblioteca de utilidades OmniFaces está disponible para JSF 2.
Publiqué esta solución mencionada por el comentario de @ BalusC como una respuesta, ya que esta es la solución más directa.
Desafortunadamente, esto no es posible en la implementación estándar de JSF. El componente y el procesador no admiten oficialmente este atributo. Sin embargo, puedes hacer un homegrow de un renderizador que maneje esto.
Dado que este es un requisito / deseo bastante común, pensé echar un vistazo a lo que es posible.
Primero, parte de la información de fondo: JSF usa por defecto ResponseWriter#writeText()
para escribir el cuerpo de la etiqueta, que escapa HTML de forma predeterminada. Nos gustaría dejar que use ResponseWriter#write()
lugar de al igual que con <h:outputText escape="false" />
. Nos gustaría extender el MessagesRenderer
de MessagesRenderer
de la implementación JSF estándar y anular el método encodeEnd()
consecuencia. Pero dado que MessagesRenderer#encodeEnd()
contiene bastante código (~ 180 líneas) que preferimos no copiar pasta para simplemente cambiar una o dos líneas después de todo, me pareció mejor reemplazar el ResponseWriter
con una implementación personalizada con ayuda de ResponseWriterWrapper
donde el writeText()
ha sido writeText()
para manejar el escape.
Entonces, terminé con esto:
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.
}
}
}
A pesar de la anotación @FacesRenderer
, la implementación predeterminada de MessagesRenderer
lo sobrescribe. Sospecho que aquí hay un error, entonces informé sobre el problema 1748 . Para que funcione de todos modos, tenemos que recurrir a 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>
Entonces, para activarlo, simplemente hazlo:
<h:messages escape="false" />
¡Y funciona! :)
Nota: lo anterior afecta a <h:messages>
solamente. Para hacer lo mismo con <h:message>
, simplemente haga lo mismo, pero reemplace en cualquier lugar "Messages"
por "Message"
(familia de componentes, tipo de renderer y nombres de clase).