Reputation: 602
I am trying to populate a map with values from inputText and inputTextArea. Also Date. In the backbean I have a map of like Map>
Basically, a Category can have many Attributes. These Attributes are input fields. For multiselect, dropdown and single select all i need is to set the attribute. But for TextArea, textField and Date I need to set the attribute plus the value which is why I have the String.
my jsf looks like
<p:dataList id="serviceCatalogueCriteria" var="category" value="#{serviceCatalogueController.allMap.keySet()}">
<div id="categoryDiv" style="overflow: hidden;">
<div class="category-header">
<h:outputText value="#{serviceCatalogueController.allMap[category.key]}" />
</div>
<div>
<!-- Text field, text area or date -->
<div class="category-text">
<ui:fragment
rendered="#{categoryService.isTextField(category) or categoryService.isTextArea(category) or categoryService.isDate(category)}">
<ui:fragment
rendered="#{categoryService.isTextField(category)}">
<p:dataList var="attribute" value="#{category.entrySet()}" >
<p:inputText
value="#{category[attribute.key]}" />
</p:dataList>
</ui:fragment>
<ui:fragment
rendered="#{categoryService.isTextArea(category)}">
<p:dataList var="attribute" value="#{category.entrySet()}" >
<p:inputTextarea rows="3" cols="70"
value="#{category[attribute.key]}"/>
</p:dataList>
</ui:fragment>
<ui:fragment rendered="#{categoryService.isDate(category)}">
<p:dataList var="attribute" value="#{category.entrySet()}" >
<p:calendar
value="#{category[attribute.key]}"
showOn="button">
</p:calendar>
</p:dataList>
</ui:fragment>
</ui:fragment>
</div>
<p:separator />
</p:dataList>
And my back bean looks like
private Map<Category,Map<Attribute,String>> allMap;
//setter and getter
The error I get is
javax.el.PropertyNotFoundException: /resources/PWAssessment/ServiceCatalogueFilters.xhtml @24,84 value="#{serviceCatalogueController.allMap[category.key]}": Property 'key' not found on type java.util.HashMap$KeySet
Why would this not work?
Upvotes: 0
Views: 1842
Reputation: 1109645
There are 2 mistakes.
<p:dataList>
can't iterate over a Set<E>
(nor Map<K, V>
). It can only iterate over List<E>
or E[]
or DataModel<E>
.
Even if it would have worked, the var="category"
represents the Category
instance itself, not some Map
. If the <p:dataList>
would have supported Set<E>
, you should just have used
<h:outputText value="#{serviceCatalogueController.allMap[category]}" />
And, equivalently, further in the code, the #{category.entrySet()}
wouldn't have worked either, as the #{category}
would represent the Category
instance itself.
The <p:dataList>
supports iterating over an array. So, this should do:
<p:dataList value="#{serviceCatalogueController.allMap.entrySet().toArray()}" var="categoryEntry">
This is Category: #{categoryEntry.key}
This is Map<Attribute,String>: #{categoryEntry.value}
...
<p:dataList value="#{categoryEntry.value.entrySet().toArray()}" var="attributeEntry">
This is Attribute: #{attributeEntry.key}
This is String: #{attributeEntry.value}
This is quite inefficient though. I strongly recommend to remodel the model as such that you just have something like a List<CategoryDTO>
. Otherwise, grab <c:forEach>
which supports efficiently iterating over a Map
:
<c:forEach items="#{serviceCatalogueController.allMap}" var="categoryEntry">
This is Category: #{categoryEntry.key}
This is Map<Attribute,String>: #{categoryEntry.value}
...
<c:forEach items="#{categoryEntry.value}" var="attributeEntry">
This is Attribute: #{attributeEntry.key}
This is String: #{attributeEntry.value}
Upvotes: 2