JSF 2.0 custom messages
Asked Answered
R

3

7

I'm using JSF 2.0. I'm using the

<h:messages>

tag to render error messages. I can use css to style my messages a little bit but I've create a composite component to render messages that can be closed and adding effects to them with some Jquery.

I've seen tutorials on how to customize the messages, but most of these rely on css and customizing the text output yet what I want to do is generate specific markup, something like

<myComp:fancyMessage text="etcetcetc error msg" type="error" />

instead of the regular message markup. Is this possible?

EDIT:

I don't want to style up jsf messages. Neither add background nor change its style, but rather create my own message html markup. Here:

http://balusc.blogspot.com/2010/07/using-html-in-jsf-messages.html

I've found how to add html to your messages. What I want is to encapsule all the html in my composite component, and then just use my composite component in this way:

<mycomp:messages/>

or

<mycomp:message for="componentID" />

where message and messages both create their own html markup

Redbug answered 14/2, 2011 at 0:32 Comment(5)
Your question is very vague. You said that you've created a composite component with some jQuery and then you're asking if it is possible to create a custom (composite) component. What is the concrete problem/question?Calli
@Calli I was just reading your blog and stumbled upon this: balusc.blogspot.com/2010/07/using-html-in-jsf-messages.html which is not exactly what I'm looking for. I missed that entry.Redbug
I apologize for my question being so vague. I meant i created a composite component to display messages. I need jsf to render messages using that composite component.Redbug
I don't want the html markup to be in the message but rather in the component.Redbug
Ah yes, I now understand what you mean.Calli
C
13

Use FacesContext#getMessageList() inside ui:repeat. Each item is a FacesMessage which has several getters.

<ui:repeat value="#{facesContext.messageList}" var="facesMessage">
    Severity: #{facesMessage.severity}<br />
    Summary: #{facesMessage.summary}<br />
    Detail: #{facesMessage.detail}<br />
    <br />
</ui:repeat>

This allows for more fine-grained HTML markup around the messages.


And it also enables you to print them as HTML with help of <h:outputText escape="false">. I might need to expand and revise my blog article sooner or later :)

Calli answered 18/2, 2011 at 2:11 Comment(2)
BalusC, I did it and it works like a charm, except for one thing. Since I'm using my own messages component (i named it: <acc:messages>) jsf cant find the messages tag so it displays the message at the end of the page. So i end up with two messages rendered, the one i created and jsf's. Is there anyway to supress warning or register my component as a message renderer?Redbug
If you mean the development warning that messages are been queued and not displayed, then sorry I don't know right now. This will however not appear when project stage is not set to development. You might want to hack this in with a <h:messages style="display: none;" />.Calli
B
3

In reply to how to set your component as message renderer:

Your component needs to extend HtmlBasicRenderer.

Then you can add your renderer to faces-config.xml

<render-kit>
    <renderer>
        <component-family>javax.faces.Messages</component-family>
        <renderer-type>javax.faces.Messages</renderer-type>
        <renderer-class>com.mypackage.MessagesRenderer</renderer-class>
    </renderer>
</render-kit>
Benjamin answered 21/2, 2011 at 22:38 Comment(2)
Hey, my composite component doesn't extend from UIComponent, I have defined it in a xhtml file. Is there no way to do it without creating a java class as a custom renderer?Redbug
@Redbug At the moment I don't know an alternative. Just startet migrating a rather big project from 1.2 to 2.0 some weeks ago. If I can find something out about this issue, I'll sure let you know.Benjamin
H
1

I know it's been a while, but thought to share this alternate solution for the benefit of others. For composites, create a backing component with a getter, then iterate over the faces messages and call remove() after collecting each message. This will get you around the "messages queued" warning without the h:messages hack.

xhtml:

<composite:interface displayName="Messages Component"
    shortDescription="Messages Component" componentType="com.company.dept.commons.ui.messages.Messages">
    <composite:attribute name="styleClass" default="" type="java.lang.String" shortDescription="CSS style class for the component" />
</composite:interface>

<composite:implementation>
    <div id="messagesComponent" class="#{cc.attrs.styleClass}">
        <ui:repeat value="#{cc.messageList}" var="message">
            #{message.severity} - #{message.detail}<br/>            
        </ui:repeat>
    </div>
</composite:implementation>

Backing component:

@FacesComponent("com.company.dept.commons.ui.messages.Messages")
public class Messages extends UINamingContainer {

    private List<FacesMessage> messages;

    public List<FacesMessage> getMessageList() {
        //preserve messages in case getter is called multiple times
        if (messages == null) {
            messages = new ArrayList<FacesMessage>();
        }

        Iterator<FacesMessage> messageItr = getFacesContext().getMessages();
        while(messageItr.hasNext()) {
            FacesMessage message = messageItr.next();
            messages.add(message);
            messageItr.remove();
        }
        return messages;
    }       
}

Note the componentType in the xhtml is set to the FacesComponent value in the code. Also, the reference to cc.messageList will trigger the call to getMessageList().

Hope this helps.

Horseleech answered 13/2, 2013 at 14:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.