java JSF - 如何以一种视觉上吸引人的方式在 <h:messages> 中格式化我的全局消息?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3709152/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 03:05:56  来源:igfitidea点击:

JSF - How can I format my global messages in <h:messages> in a visually appealing way?

javacssweb-applicationsjsfmyfaces

提问by Jim Tough

I'm not too familiar with using the <h:messages>element in JSF. What I'm trying to do is use it to display a list of global messages of varying severity that are generated by a method in my backing bean. Getting the messages into the FacesContextisn't too much of a problem, and my code is along these lines:

我不太熟悉<h:messages>在 JSF 中使用该元素。我想要做的是使用它来显示由我的支持 bean 中的方法生成的不同严重性的全局消息列表。将消息放入FacesContext不是太大的问题,我的代码是这样的:

FacesMessage message;
FacesContext context = 
    FacesContext.getCurrentInstance();
message = new FacesMessage(
    FacesMessage.SEVERITY_INFO,
    "test message summary 1",
    "test message detail 1");
context.addMessage(null, message);
message = new FacesMessage(
    FacesMessage.SEVERITY_WARN,
    "test message summary 2",
    "test message detail 2");
context.addMessage(null, message);
message = new FacesMessage(
    FacesMessage.SEVERITY_ERROR,
    "test message summary 3",
    "test message detail 3");
context.addMessage(null, message);
// add more messages...

That all works fine. My problem is with trying to make the output of the <h:messages>tag look good on the page. Here is the relevant piece of my JSP file:

这一切正常。我的问题是试图让<h:messages>标签的输出在页面上看起来不错。这是我的 JSP 文件的相关部分:

<h:panelGrid border="1" columns="1" id="messagesPanelGrid">
    <h:messages 
        id="messagesOutput"
        showSummary="true"
        showDetail="true" 
        layout="table"
        infoClass="info-message"
        warnClass="warn-message"
        errorClass="error-message"
        fatalClass="fatal-message" 
        globalOnly="true" />
</h:panelGrid>

This consistently looks like crap on the page. I am using an external CSS stylesheet to define styling classes. I've tried using layout="list"but then the list items span the whole page and make any block styling look bad, so I switched to layout="table". I framed the <h:messages>inside a <h:panelGrid>so I would have some block-level element that I could apply styles to. It still doesn't look particularly nice.

这在页面上始终看起来像废话。我正在使用外部 CSS 样式表来定义样式类。我试过使用layout="list"但随后列表项跨越整个页面并使任何块样式看起来都很糟糕,所以我切换到layout="table". 我将<h:messages>内部框起来,<h:panelGrid>这样我就有了一些可以应用样式的块级元素。看起来还是不是特别好看。

What I'm getting now:

我现在得到的是:

<table border="1" id="myForm:messagesOutput">
    <tr><td class="error-message"><span>no port name match Could not match reported port name XXXX to a known port for vessel VESSEL A</span></td></tr>
    <tr><td class="error-message"><span>no port name match Could not match reported port name YYYY to a known port for vessel VESSEL B</span></td></tr>
    <tr><td class="error-message"><span>no port name match Could not match reported port name YYYY to a known port for vessel VESSEL C</span></td></tr>
    <tr><td class="error-message"><span>no port name match Could not match reported port name ZZZZ to a known port for vessel VESSEL D</span></td></tr>
    <tr><td class="warn-message"><span>arrival date missing No arrival date provided for vessel VESSEL B</span></td></tr>
</table>

What I'm trying to get:

我想得到什么:

<table border="1" id="myForm:messagesOutput" class="myMessagesTableClass">
    <thead><tr"><td>SUMMARY</td><td>DETAIL</td></tr></thead>
    <tr><td class="error-message-summary"><span>no port name match</span></td><td class="error-message-detail"><span>Could not match reported port name XXXX to a known port for vessel VESSEL A</span></td></tr>
    <tr><td class="error-message-summary"><span>no port name match</span></td><td class="error-message-detail"><span>Could not match reported port name YYYY to a known port for vessel VESSEL B</span></td></tr>
    <tr><td class="error-message-summary"><span>no port name match</span></td><td class="error-message-detail"><span>Could not match reported port name YYYY to a known port for vessel VESSEL C</span></td></tr>
    <tr><td class="error-message-summary"><span>no port name match</span></td><td class="error-message-detail"><span>Could not match reported port name ZZZZ to a known port for vessel VESSEL D</span></td></tr>
    <tr><td class="warn-message-summary"><span>arrival date missing</span></td><td class="warn-message-detail"><span>No arrival date provided for vessel VESSEL B</span></td></tr>
</table>
  • Messages are still in a table layout, but the "summary" and "detail" are in separate columns
  • Generated table has a CSS class directly assigned to it
  • The "summary" and "detail" parts of the message have separate style classes
  • NICE TO HAVE: Table header row
  • 消息仍然在表格布局中,但“摘要”和“详细信息”在单独的列中
  • 生成的表有一个直接分配给它的 CSS 类
  • 消息的“摘要”和“详细信息”部分具有单独的样式类
  • 好东西:表格标题行

SCREENSHOT:
alt text

截屏:
替代文字

Does anyone out there work with <h:messages>tags and have some ideas on how I can achieve this?

有没有人使用<h:messages>标签工作并对我如何实现这一目标有一些想法?

I'm not sure if it matters for this question, but I'm using MyFaces 1.2. I can't upgrade to 2.x at the moment.

我不确定这个问题是否重要,但我使用的是 MyFaces 1.2。我目前无法升级到 2.x。

回答by BalusC

After all, you want to change the HTML output. This really can't be done with CSS. CSS is more to give the existing HTML elements a layout, not to modify them. Apart from fiddling in JavaScript (which isn't easy in this particular case), you'd like to have JSF change its HTML output. There are basically two ways:

毕竟,您想要更改 HTML 输出。这真的不能用 CSS 来完成。CSS 更多的是给现有的 HTML 元素一个布局,而不是修改它们。除了在 JavaScript 中摆弄(在这种特殊情况下这并不容易),您还希望 JSF 更改其 HTML 输出。基本上有两种方式:

  1. Supply your own MessagesRendererso that it renders messages the way you want. Extend the base renderer class as used in MyFaces (sorry, since I don't use MyFaces I can't tell from top of head which class it is for MyFaces, you need to consult its API docs) and register it in faces-configas follows:

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

    Here, com.example.CustomMessagesRendereris thus the custom renderer you've implemented. You'd like to override the encodeEnd()method of the standard renderer to have it to output HTML the desired way. This is too much code to post as an example here, but just looking in the source code of the default messages renderer should give enough hints.

  2. Collect the messages in a List<FacesMessage>with help of FacesContext#getMessages()and just display them with help of c:forEachor t:dataListand plain vanilla HTML. E.g.

    public List<FacesMessage> getMessages() {
        List<FacesMessage> messages = new ArrayList<FacesMessage>();
        Iterator<FacesMessage> iter = FacesContext.getCurrentInstance().getMessages();
        while (iter.hasNext()) {
            messages.add(iter.next());
        }
        return messages;
    }
    

    with

    <table border="1" id="myForm:messagesOutput" class="myMessagesTableClass">
      <thead><tr><td>SUMMARY</td><td>DETAIL</td></tr></thead>
      <tbody>
        <c:forEach items="#{bean.messages}" var="message">
          <c:set var="type" value="#{message.severity == 'SEVERITY_ERROR' ? 'error' : 'warn'}" />
          <tr>
            <td class="#{type}-message-summary"><span>#{message.summary}</span></td>
            <td class="#{type}-message-detail"><span>#{message.detail}</span></td>
          </tr>
        </c:forEach>
      </tbody>
    </table>
    

    In JSF2, you'd have used #{facesContext.messageList}directly instead of #{bean.messages}.

  1. 提供您自己的,MessagesRenderer以便它以您想要的方式呈现消息。扩展在 MyFaces 中使用的基本渲染器类(抱歉,因为我不使用 MyFaces 我无法从头顶判断它是用于 MyFaces 的类,您需要查阅其 API 文档)并将其注册faces-config如下:

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

    com.example.CustomMessagesRenderer就是您实现的自定义渲染器。您想覆盖encodeEnd()标准渲染器的方法,让它以所需的方式输出 HTML。这是太多的代码,无法在此处作为示例发布,但只需查看默认消息渲染器的源代码即可提供足够的提示。

  2. 在 的List<FacesMessage>帮助下收集消息,FacesContext#getMessages()并在c:forEacht:dataList和普通 HTML 的帮助下显示它们。例如

    public List<FacesMessage> getMessages() {
        List<FacesMessage> messages = new ArrayList<FacesMessage>();
        Iterator<FacesMessage> iter = FacesContext.getCurrentInstance().getMessages();
        while (iter.hasNext()) {
            messages.add(iter.next());
        }
        return messages;
    }
    

    <table border="1" id="myForm:messagesOutput" class="myMessagesTableClass">
      <thead><tr><td>SUMMARY</td><td>DETAIL</td></tr></thead>
      <tbody>
        <c:forEach items="#{bean.messages}" var="message">
          <c:set var="type" value="#{message.severity == 'SEVERITY_ERROR' ? 'error' : 'warn'}" />
          <tr>
            <td class="#{type}-message-summary"><span>#{message.summary}</span></td>
            <td class="#{type}-message-detail"><span>#{message.detail}</span></td>
          </tr>
        </c:forEach>
      </tbody>
    </table>
    

    在 JSF2 中,您会#{facesContext.messageList}直接使用#{bean.messages}.

回答by Bozho

As BalusC commented, this is a matter of CSS skills. However, I have one practical advice:

正如 BalusC 评论的那样,这是一个 CSS 技能问题。但是,我有一个实用的建议:

  • open the page
  • see "view source"
  • copy the resulting file and try applying your css skills to the generated HTML.
  • alternatively, use FireBug and add styles dynamically and check what it looks like.
  • 打开页面
  • 见“查看源代码”
  • 复制生成的文件并尝试将您的 css 技能应用于生成的 HTML。
  • 或者,使用 FireBug 并动态添加样式并检查它的外观。