JSF - Как я могу отформатировать мои глобальные сообщения в <h: messages> визуально привлекательным способом? - PullRequest
4 голосов
/ 14 сентября 2010

Я не слишком знаком с использованием элемента <h:messages> в JSF. То, что я пытаюсь сделать, это использовать его для отображения списка глобальных сообщений различной степени серьезности, которые генерируются методом в моем компоненте поддержки. Получение сообщений в 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...

Это все отлично работает. Моя проблема в том, чтобы попытаться сделать вывод тега <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>

Это постоянно выглядит как дерьмо на странице. Я использую внешнюю таблицу стилей CSS для определения классов стилей. Я пытался использовать layout="list", но затем элементы списка занимали всю страницу и заставляли любой стиль блока выглядеть плохо, поэтому я переключился на layout="table". Я подставил <h:messages> внутри <h:panelGrid>, чтобы у меня был элемент блочного уровня, к которому я мог бы применить стили. Это все еще не выглядит особенно хорошо.

Что я получаю сейчас:

<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>

Что я пытаюсь получить:

<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>
  • Сообщения по-прежнему находятся в макете таблицы, но «сводка» и «подробности» находятся в отдельных столбцах
  • Сгенерированная таблица имеет класс CSS, непосредственно присвоенный ей
  • Части сообщения "summary" и "detail" имеют отдельные классы стилей
  • ХОРОШО ИМЕТЬ: строка заголовка таблицы

SCREENSHOT:
alt text

Кто-нибудь там работает с тегами <h:messages> и есть идеи, как мне этого добиться?

Я не уверен, имеет ли это значение для этого вопроса, но я использую MyFaces 1.2. Я не могу перейти на 2.x в данный момент.

Ответы [ 2 ]

7 голосов
/ 14 сентября 2010

В конце концов, вы хотите изменить вывод HTML.Это действительно не может быть сделано с помощью CSS.CSS больше для того, чтобы придать существующим элементам HTML макет, а не изменять их.Помимо работы с JavaScript (что не так просто в данном конкретном случае), вы бы хотели, чтобы JSF изменил вывод HTML.Есть два основных способа:

  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:forEach или t: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}.

2 голосов
/ 14 сентября 2010

Как прокомментировал BalusC, это вопрос навыков CSS. Однако у меня есть один практический совет:

  • открыть страницу
  • см. «Просмотр источника»
  • скопируйте полученный файл и попробуйте применить свои навыки CSS к сгенерированному HTML.
  • альтернативно, используйте FireBug и динамически добавляйте стили и проверяйте, как он выглядит.
...