JarochoEngineer
JarochoEngineer

Reputation: 1787

Render map key in first row of h:dataTable only

I have been searching on how to display a Map<String, ArrayList<String>> using c:forEach. I am attempting to print a list of words in alphabetical order and showing the key once in the same line than the first element in the ArrayList.

A Apple
  Arpa
  Adverb

B Background
  Ball
  Ballad
...

The signature of the map is:

private Map<String, ArrayList<String>> procedures; 

I'm rendering it as below:

<c:forEach items="#{obj.procedures}" var="entry" varStatus="counter"> 
    <h:column><h:outputText value="&#160;#{entry.key}"/> </h:column>
    <h:dataTable value="#{entry.value}" var="foo">                                       
        <h:column><h:outputText value="&#160;&#160;" /></h:column>                    
        <h:column><h:outputText value="&#160;#{foo}" /></h:column>                    
    </h:dataTable>
    <p:separator></p:separator>
</c:forEach>

However, the result is slightly different because the first letter appears one line above of the first record instead of showing in the same line than the first record in the list of values.

Current result:

A 
  Apple
  Arpa
  Adverb
_________________
B 
  Background
  Ball
  Ballad
    ...

Cheers

Upvotes: 0

Views: 354

Answers (1)

BalusC
BalusC

Reputation: 1108722

You need to render it inside the <h:dataTable>, not outside. Just move the <h:column> rendering the map key back into the <h:dataTable>.

<c:forEach items="#{obj.procedures}" var="entry">
    <h:dataTable value="#{entry.value}" var="foo">
        <h:column>#{entry.key}</h:column>
        <h:column>#{foo}</h:column>
    </h:dataTable>
</c:forEach>

This will produce:

A  Apple
A  Arpa
A  Adverb

B  Background
B  Ball
B  Ballad

Then, in order to let it show up only in the first row, simply check if the table's current row index equals to 0. You can get it by consulting UIData#getRowIndex(). You can from inside a <h:column> access the parent <h:dataTable>, which is an UIData, via the #{component.namingContainer} expression.

<c:forEach items="#{obj.procedures}" var="entry">
    <h:dataTable value="#{entry.value}" var="foo">
        <h:column><h:outputText value="#{entry.key}" rendered="#{component.namingContainer.rowIndex eq 0}" /></h:column>
        <h:column>#{foo}</h:column>
    </h:dataTable>
</c:forEach>
A  Apple
   Arpa
   Adverb

B  Background
   Ball
   Ballad

By the way, use CSS margin, padding and border for whitespace and borders, not non-breaking spaces or separator components. It makes your markup unnecessarily bloated and maintenance-unfriendly.

Upvotes: 1

Related Questions