Как отобразить разные значения из разных типов объектов в одной таблице данных? - PullRequest
3 голосов
/ 12 июня 2011

У меня есть объект (Ticket), в котором есть список других объектов (Message).Сообщение является абстрактным и имеет несколько подклассов - например, EditMessage, CreationMessage и так далее.Так что объект Ticket содержит смесь этих сообщений, и они упорядочены по времени их создания.

Теперь я хочу отобразить все эти сообщения на странице Facelets, и мне нужно вывести значения полей, специфичные дляэтот тип сообщения: т.е. editedField в EditMessage, userName в CreationMessage, ...

Наиболее очевидный способ, по-видимому, использует h: dataTable:

<h:dataTable value="#{ticketController.ticket.messages}" var="msg" >
    // determine type of message, cast, and use <c:if> to output needed values
</h:dataTable>

Проблема в том, что язык выражений Faceletsне имеет "instanceof" и бросает.Насколько я вижу, это можно решить, используя некрасивое циклическое переключение на управляемый компонент, определяя тип сообщения в стандартном Java, возвращая сообщение нужного типа, и т. Д.

Есть лилучший, более понятный и лаконичный способ сделать это?

Решение

Моя главная проблема была стег.Оказалось, что это тег JSTL, поэтому он имеет немного другой жизненный цикл рендеринга.Вместо этого я сейчас используюи его «визуализированный» атрибут.

Некоторый код:

<h:dataTable value="#{ticketController.ticket.messages}" var="msg" >
    <h:column>
        <h:panelGroup rendered="#{msg.class.name == 'org.rogach.tsnt.TextMessage'}" >
            <h:outputText value="msg.text" />
        </h:panelGroup>
        <h:outputText value="#{msg.creationTime}" />
    </h:column>
</h:dataTable>

И приведение не требуется.

1 Ответ

3 голосов
/ 12 июня 2011

Вместо instanceof , сравните имя класса объекта.
Скажите: <c:if test="${xxx.class.name == 'CreationMessage'}"> или c: выберите
И вам не понадобится приведение с EL.Если у объекта нет какого-либо свойства, которое вы указали, он выдаст исключение, если у него все в порядке.

...