I have a List that contains a map like this:
Map<String, Long> count = new HashMap<>();
count.put("totalMessageCount", 5L);
Map<String, Map<String, Long>> names = new HashMap<>();
names.put("someKey", count);
List<Map<String, Map<String, Long>>> list = new ArrayList<>();
list.add(names);
I am sending this list from controller to the View.
I have tried this:
<table>
<tr th:each="element : ${list}">
<td th:text="${element.key}"></td>
<td th:text="${element.value}"></td>
</table>
I get an error:
org.springframework.expression.spel.SpelEvaluationException: EL1008E: Property or field 'key' cannot be found on object of type 'java.util.HashMap' - maybe not public or not valid?
at org.springframework.expression.spel.ast.PropertyOrFieldReference.readProperty(PropertyOrFieldReference.java:217)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.getValueInternal(PropertyOrFieldReference.java:104)
at org.springframework.expression.spel.ast.PropertyOrFieldReference.access$000(PropertyOrFieldReference.java:51)
at
...
Any help is appreciated.
You need another level of nesting, most probably.
<table>
<th:block th:each="map : ${list}">
<tr th:each="e : ${map}">
<td th:text="${e.key}"></td>
<td th:text="${e.value}"></td>
</tr>
</th:block>
</table>
As key and value are properties of a Map.Entry.
Related
I want directly push the selected option. But i dont find a solution. Maybe u can help me?
I have a table with a list of entities. And i will offer a select for every entity. But i want to save the selection directly.
I need the entry.id and the cat.id.
This is what i have.
<form class="myForms" id="uploadCheckerForm" method="post" th:action="#{uploadStatus}">
<table>
<tr th:replace="fragment/form-fragments::checkerMainLine()"></tr>
<tr th:each="entry : ${uploadList}">
<td><select th:id="transactionCategory" th:name="transactionCategory">
<option>Select</option>
<option th:each="cat : ${transactionCategoryList}"
th:text="${cat.name}" th:value="${cat.id}">
</option></select>
</td>
<td th:text="${entry.Comment}">
</tr>
</table>
</form>
What have i to do, that it directly post this infos?
Thanks for help!
I would append some unique identifier of your entry to the name of your <select> with some sort of separator and then accept form data on backend to a Map. Kinda like this:
HTML
<form class="myForms" id="uploadCheckerForm" method="post" th:action="#{uploadStatus}">
<table>
<tr th:replace="fragment/form-fragments::checkerMainLine()"></tr>
<tr th:each="entry : ${uploadList}">
<td><select id="transactionCategory" th:name="'transactionCategory_' + ${entry.guid}">
<option>Select</option>
<option th:each="cat : ${transactionCategoryList}"
th:text="${cat.name}" th:value="${cat.id}">
</option></select>
</td>
<td th:text="${entry.Comment}">
</tr>
</table>
</form>
Controller
#PostMapping( "/uploadStatus" )
public String uploadStatus( #RequestParam Map<String, Long> params ) {
for ( Map.Entry<String, Long> entry : params.entrySet() ) {
if ( entry.getKey().startsWith( "transactionCategory_" ) ) continue; // skip
Long entryId = Long.parseLong( entry.getKey().replace( "transactionCategory_", "" ) ); // get entry ID
SomeDAO.instance().uploadStatus( entryId, entry.getValue() ); // do what you need to do with id of entry and chosen category ID
}
return "redirect:/";
}
I am trying to iterate list and display values in thymeleaf but i am getting below Error
Exception processing template "customers/Customers": Exception evaluating SpringEL expression: "list.customerid" (customers/Customers:94)
EL1008E:(pos 5): Property or field 'customerid' cannot be found on object of type 'java.util.LinkedHashMap' - maybe not public?
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
List<CustomerAccounts> acountsList = custService.findCustomer(mobilenumber, accountnumber);
System.out.println("acountsList size:-"+acountsList.size());
if(acountsList.size() != 0){
for(CustomerAccounts custAccounts :acountsList){
DcbCustomerAccount accountMaster = custService.findAccountMaster(custAccounts.getMobilenumber().substring(2), custAccounts.getAccountNumber());
Map<String, Object> map = new LinkedHashMap<String, Object>();
if(accountMaster !=null){
System.out.println("Customer Id:"+accountMaster.getId().getCustomerid());
map.put("customerid", accountMaster.getId().getCustomerid());
map.put("name", custAccounts.getName());
map.put("accountNumber", custAccounts.getAccountNumber());
map.put("mobilenumber", custAccounts.getMobilenumber());
map.put("createdDate", custAccounts.getCreatedDate());
map.put("status", "Activated");
}
list.add(map);
}
System.out.println("List Size:-"+list.size());
model.addAttribute("acountsList", list);
}
<tr th:each="list,iterStat : ${acountsList}">
<!-- <td th:text="${list.id}">CustomerID</td> -->
<td th:text="${list.customerid}">CustomerID</td>
<td th:text="${list.name}">Customer Name</td>
<td th:text="${list.accountNumber}">Account Number</td>
<td th:text="${list.mobilenumber}">Mobile Number</td>
<td th:text="${list.createdDate}">Created Date</td>
<td th:text="${list.status}">Created Date</td>
</tr>
I am trying to put values in map and add to list. Finally list object return is model attribute.
Whats wring in my code?
I've data in the below format.
Map<String, Map<String,List<String>>>
example - {ProfileAdaptarRepository={active=[true,false,true,true]}}}
I did set page context in mymap in the below scriptlets and it works absolutely fine.
<% pageContext.setAttribute("mymap",example);%>
I need data in the below html tabular format:
Sample HTML source code for the above image.
<html>
<body>
<table border="1">
<tr>
<th>Component</th>
<th>Properties</th>
<th>J01</th>
<th>J02</th>
<th>W01</th>
<th>W02</th>
</tr>
<tr>
<td>StoreConfiguration</td>
<td>active</td>
<td>true</td>
<td>false</td>
<td>true</td>
<td>false</td>
</tr>
<tr>
<td>DynamoConfiguration</td>
<td>enabled</td>
<td>true</td>
<td>false</td>
<td>true</td>
<td>false</td>
</tr>
</table>
</body>
</html>
I tried to present the above data in webpage using the below jstl code, but it didn't work for plural component values (more than 1 components)
<c:forEach var = "comp" items="${mymap}">
<tr>
<td>${comp.key}</td>
<c:forEach var="prop" items="${comp.value}">
<td>${prop.key}</td>
<c:forEach var="val" items="${prop.value}">
<td>${val}</td>
</c:forEach>
</c:forEach>
</tr>
</c:forEach>
Can someone please help or guide me in achieving the desired tabular format?
Many Thanks in advance..:)
I was able to run your code with multiple components. I created a data structure like yours with
List<String> myListStore = new ArrayList<>();
List<String> myListDynamo = new ArrayList<>();
List<String> myListProfile = new ArrayList<>();
Map<String, List<String>> myMapStore = new HashMap<>();
Map<String, List<String>> myMapDynamo = new HashMap<>();
Map<String, List<String>> myMapProfile = new HashMap<>();
Map<String, Map<String, List<String>>> myBigMap = new HashMap<>();
myListDynamo.add("true");
myListDynamo.add("false");
myListDynamo.add("true");
myListDynamo.add("false");
myMapDynamo.put("enabled", myListDynamo);
myBigMap.put("Dynamo", myMapDynamo);
myListStore.add("true");
myListStore.add("false");
myListStore.add("true");
myListStore.add("true");
myMapStore.put("disabled", myListStore);
myBigMap.put("Store", myMapStore);
myListProfile.add("true");
myListProfile.add("false");
myListProfile.add("true");
myListProfile.add("true");
myMapProfile.put("disabled", myListProfile);
myBigMap.put("Profile", myMapProfile);
request.setAttribute("mymap", myBigMap);
I used your exact jstl code and was able to generate the table. Are you sure that your data is in the correct format in the data structure?
I have my response Object as which contains getter and setters for the Map -
public class DataResponse {
private Map<String, List<String>> attributes = new LinkedHashMap<String, List<String>>();
public Map<String, List<String>> getAttributes() {
return attributes;
}
public void setAttributes(Map<String, List<String>> attributes) {
this.attributes = attributes;
}
}
In the above object, I have a Map of String and List<String>. In the map, keys are my table header and the value in the map is the table data for that header.
Suppose if this is the value in the map -
FirstName is the Key in the same Map
DAVID, RON, HELLO are the values in the map as the List for that key.
Similarly,
LastName is the Key in the same Map
JOHN, PETER, TOM are the values in the map as the List for the `LastName` key.
Then my Table should look like this
FirstName LastName
David JOHN
RON PETER
HELLO TOM
I need to generate my above table dynamically as am passing my dataResponse object to my JSP page as mentioned below -
DataResponse dataResponse = some_code_here;
req.setAttribute("data", dataResponse);
WebUtil.forward(req, resp, this, "/admin/test.jsp");
And below is my table in JSP in which I am using my above object to generate the table in the above format
<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="1" style="text-align: center;">
<TR>
<c:forEach var="h" items="${data.attributes}">
<TH>${h.key}</TH>
</c:forEach>
</TR>
//iterate again
<c:forEach var="h" items="${data.attributes}">
//h.value is ArrayList so we can iterate with c:forEach
<c:forEach var="headers" items="${h.value}">
<TR>
<TD>${headers}</TD>
</TR>
</c:forEach>
</c:forEach>
</TABLE>
But somehow my tables are not getting shown in the way I am trying to show in my above example. All the keys are getting shown properly in the Table Headers but all the values are getting shown only in first column.
And size of the list will be same for all the keys.
Any thought how this can be done?
UPDATE:-
<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="1" style="text-align: center;">
<TR>
<c:forEach var="h" items="${data.attributes}">
<TH>${h.key}</TH>
</c:forEach>
</TR>
//iterate again
<c:forEach var="h" items="${data.attributes}">
<TR>
<c:forEach var="headers" items="${h.value}">
<TD>${headers}</TD>
</c:forEach>
</TR>
</c:forEach>
</TABLE>
This gives me -
FirstName LastName
David RON HELLO
JOHN PETER TOM
<%
// Create an ArrayList with test data
ArrayList list = new ArrayList();
Map person1 = new HashMap();
person1.put("name", "A");
person1.put("lastname", "A1";
list.add(person1);
Map person2 = new HashMap();
person2.put("name", "B");
person2.put("lastname", "B1");
list.add(person2);
Map person3 = new HashMap();
person3.put("name", "C");
person3.put("lastname", "");
list.add(person3);
pageContext.setAttribute("persons", list);
%>
<html>
<head>
<title>Search result: persons</title>
</head>
<body bgcolor="white">
Here are all persons matching your search critera:
<table>
<TH>Name</th>
<TH>Id</th>
<c:forEach items="${persons}" var="current">
<tr>
<td><c:out value="${current.name}" /><td>
<td><c:out value="${current.lastname}" /><td>
</tr>
</c:forEach>
</table>
This approach is easier and suggested.
If u still want to stick with your code, you can use jsp tags instead of jstl tags to achieve your goal as follow
<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="1" style="text-align: center;">
<TR>
<c:forEach var="h" items="${data.attributes}">
<TH>${h.key}</TH>
</c:forEach>
</TR>
//use jsp scriplets to acces both list simultaneoulsy
<% List data= request.getAttribute("data")==null?null:(List) request.getAttribute("data");
List Names=data.get(0);
List LastNames=data.get(1);
for(int i=0;i<Names.length();i++){ %>
<td><%=Names.get(i)%></td><td><%=LastNames.get(i)%></td>
<%
}
%>
i have a
Map<ArrayList<String>, ArrayList<String> myMap = new HashMap<ArrayList<String>,ArrayList<String>>();
List<String> list1 = new ArrayList<String>();
list1.add("Administrator");
list1.add("Lookup Configuration");
List<String> list2 = new ArrayList<String>();
list2.add("User Creation");
list2.add("Branch Creation");
list2.add("Country");
list2.add("Language"):
the above is dummy data, i am creating menu management like this
Administrator (MenuName)
--User Creation (item1)
--Branch Creation (item2)
Lookup Creation (MenuName)
--Country (item1)
--Currency (item2)
i am writing jstl like this
Map,ArrayList> myMap = new LinkedHashMap,ArrayList>();
and i am doing like this
<c:forEach items="${mainMenu}" var="myMenu">
<c:forEach items="${myMenu.key}" var="menuName" varStatus="loop">
<li id="lookup" class="mail">${menuName}<span>26</span>
<ul class="sub-menu">
<c:forEach items="${myMenu.value}" var="items" varStatus="loop">
<li><em>02</em>${items.itemName}<span>14</span></li>
</c:forEach>
</ul>
</li>
</c:forEach>
</c:forEach>
i am getting key perfect, but i am struck the value
and the values are not iterating the realted key
any help would be apreciated
Regards
Pradeep
I am not sure, but maybe you want something like this:
<%
Map<String, List<String>> myMap = new LinkedHashMap<String,List<String>>();
request.setAttribute("mainMenu", myMap);
List<String> adminItemsList = new ArrayList<String>();
adminItemsList.add("User Creation");
adminItemsList.add("Branch Creation");
List<String> lookupItemsList = new ArrayList<String>();
lookupItemsList.add("Country");
lookupItemsList.add("Language");
myMap.put("Administrator", adminItemsList);
myMap.put("Lookup Configuration", lookupItemsList);
%>
<c:forEach items="${mainMenu}" var="myMenu">
<li id="lookup" class="mail">${myMenu.key}<span>26</span>
<ul class="sub-menu">
<c:forEach items="${myMenu.value}" var="item" varStatus="loop">
<li><em>02</em>_${item}_<span>14</span></li>
</c:forEach>
</ul>
</li>
</c:forEach>
out:
Administrator26
02_User Creation_14
02_Branch Creation_14
Lookup Configuration26
02_Country_14
02_Language_14
I used LinkedHashMap to remember order of keys i putted in Map.
Are you using the correct data structure?
Do you mean:
Administrator
--User Creation
--Branch Creation
Lookup Configuration
--Country
--Currency
Wouldn't this be a map of lists? : Map<String,List<String>>
Then you could have a nested loop where you iterate over each key and then over that key's values.
its really helpfull your both posts, thank you very very much
i got the solution on both of your answers
here it is
my map is Map<String,List<String> myMenu = new HashMap<String, List<String>>();
<c:forEach items="${myMenu}" var="menuName" varStatus="loop">
<li id="lookup" class="mail">${menuName.key}
<ul class="sub-menu">
<c:forEach items="${menuName.value}" var="item" varStatus="loop">
<li>${item.itemName}</li>
</c:forEach>
</ul>
</li>
</c:forEach>