Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ui:repeat doesn't work with Map

I have a Map of key / values, which I initialize in @PostConstruct as follows:

Map<String, String> myMap;

@PostConstruct
public void init() {

  myMap=new LinkedHashMap<String, String>();
  myMap.put("myKey","myValue");

}

public Map<String, String> getMyMap() {
    return myMap;
}

public void setMyMap(Map<String, String> myMap) {
    this.myMap = myMap;
}

When I try to iterate over this Map with <ui:repeat> like shown bellow, and I set a break point on the getter for the Map, I notice that it is not getting called, and so nothing is printed:

<ice:panelGroup>
    <ui:repeat items="#{myBean.myMap}" var="entry" varStatus="loop">
        <input type="checkbox" name="myCheckBoxes" value="#{entry.value}" />
        <span class="#{fn:contains(entry.value,'g') ? 'bold-style' : ''}">#{entry.key}</span>
    </ui:repeat>
</ice:panelGroup>

But when replacing above code with <c:foreach>, everything works fine, and the list is printed as expected, any ideas why I am getting such behavior?

like image 337
Mahmoud Saleh Avatar asked Dec 18 '11 15:12

Mahmoud Saleh


3 Answers

UPDATE: JSF 2.3 (since 2017) supports this out of the box.

Unfortunately, UIData and UIRepeat have no support for iterating over a map in JSF.

If this bothers you (I guess it does), please vote for the following issue and if possible leave a comment that explains how you feel about this:

http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-479

In the mean time, you can iterate over a Map with some little helper code:

/**  * Converts a Map to a List filled with its entries. This is needed since   * very few if any JSF iteration components are able to iterate over a map.  */ public static <T, S> List<Map.Entry<T, S>> mapToList(Map<T, S> map) {      if (map == null) {         return null;     }      List<Map.Entry<T, S>> list = new ArrayList<Map.Entry<T, S>>();     list.addAll(map.entrySet());      return list; } 

Then define an EL function in a *-taglib.xml file like this:

<namespace>http://example.com/util</namespace>   <function>     <function-name>mapToList</function-name>     <function-class>com.example.SomeClass</function-class>     <function-signature>java.util.List mapToList(java.util.Map)</function-signature> </function> 

And finally use it on a Facelet like this:

<html xmlns:util="http://example.com/util">      <ui:repeat value="#{util:mapToList(someDate)}" var="entry" >         Key = #{entry.key} Value = #{entry.value} <br/>     </ui:repeat> 
like image 58
Arjan Tijms Avatar answered Sep 25 '22 07:09

Arjan Tijms


<a4j:repeat value="#{myBean.myMap.entrySet().toArray()}" var="_entry">
        <h:outputText value="#{_entry.key}"/><br/>
        <h:outputText value="#{_entry.value}"/>
</a4j:repeat>

also use with <ui:repeat>

like image 40
user1483443 Avatar answered Sep 22 '22 07:09

user1483443


Seems to work for me on JSF 1.2, hope it helps someone...

    <h:panelGroup>
      <ul>
        <ui:repeat value="#{myBean.myMap.keySet().toArray()}" var="key">
          <li>key:#{key}</li>
          <li>value:#{myBean.myMap[key]}</li>
        </ui:repeat>
      </ul>
    </h:panelGroup>
like image 20
c30 Avatar answered Sep 26 '22 07:09

c30