开发者

How to display different values from different object types in a single dataTable?

I have an object (Ticket), which has a list of other objects (Message). Message is abstract, and has several subclasses - like EditMessage, CreationMessage, and so on. So that Ticket object contai开发者_Python百科ns a mix of that messages, and they are ordered by their creation time.

Now I want to display all those messages in a Facelets page, and I need to output values of fields, specific for that message type: i.e., editedField in EditMessage, userName in CreationMessage, ...

The most obvious way seems to use 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>

The problem is that Facelets expression language does not have "instanceof" and casts. As far as I can see, this can be solved using some ugly round-tripping to managed bean, determining type of message in standard Java, return message of needed type, ... and so on.

Is there a better, more understandable and concise way of doing this?


Solution

My main problem was with <c:if> tag. It turned out that it is a JSTL tag, so it has slightly different rendering life cycle. Instead of it, I now use <h:panelGroup> and its "rendered" attribute.

Some code:

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

And no cast is ever needed.


Instead of instanceof, compare the name of the object's class.
Say: <c:if test="${xxx.class.name == 'CreationMessage'}"> or c:choose
And you won't need any cast with EL. If the object doesn't have some property you specified it will give an exception, if it does have it's OK.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜