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>
Related
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.
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>
<%
}
%>
MVC - servlet forwards request to JSP.
In servlet i created list (java.util.List) of categories, attached this list to servlet context, and forwards request to JSP page:
public class Category{
private Integer id;
private String name;
private Category parentCategory;
...
//getters and setters
}
This class represents category/subcategory (if parentCategory field is null, then it is top level category).
Categories that have same parent, are its subcategories, and they are mapped to nested unordered list in JSP.
Example: result should look similar to next HTML code:
<ul class="droprightMenu">
<li>Category 1
<ul class="droprightMenu">
<li>Category 1.1</li>
<li>Category 1.2</li>
<li>Category 1.3</li>
<ul class="droprightMenu">
<li>Category 1.3.1</li>
<li>Category 1.3.2</li>
<li>Category 1.3.3</li>
<li>Category 1.3.4</li>
</ul>
<li>Category 1.4</li>
</ul>
</li>
<li>Category 2</li>
<li>Category 3</li>
<ul class="droprightMenu">
<li>Category 3.1</li>
<li>Category 3.2</li>
<ul class="droprightMenu">
<li>Category 3.2.1</li>
<li>Category 3.2.2</li>
</ul>
<li>Category 3.3</li>
<li>Category 3.4</li>
</ul>
<li>Category 4</li>
</ul>
I don't know how to loop through this list in JSP. It should probably be done with some combination of different JSTL loops, or JSP scriptlets, maybe some recursion.
Appreciate any help.
If you don't know the depth of the category tree, you can still generate your menu using recursion.
Using the same Model as Loc in the previous response, you have to define a jsp page called menuitem.jsp, which will be called recursively:
<li>
${menuitem.name}
<c:if test="${fn:length(menuitem.subCategories) gt 0}">
<ul class="droprightMenu">
<c:forEach var="menuitem" items="${menuitem.subCategories}">
<c:set var="menuitem" value="${menuitem}" scope="request" />
<jsp:include page="menuitem.jsp" />
</c:forEach>
</ul>
</c:if>
</li>
In our main JSP page, initialise the variable menuitem and include the jsp.
<c:set var="menuitem" value="${rootMenu}" scope="request" />
<jsp:include page="menuitem.jsp" />
You need to populate your Model like this:
public class Category{
private Integer id;
private String name;
private Category parentCategory;
private List<Category> subCategories;
...
//getters and setters
}
In Servlet, You need to have LIST of Category LEVEL 1 ( Parent is NULL ).
List<Category> rootCategories = getAllCategoriesLevel1();
request.setAttribute("rootCategories", rootCategories );
In JSP ( Need 3 loops OR 4,5 loops )
<c:forEach items="${rootCategories}" var="categoryLevel1">
// ...
<c:forEach items="${categoryLevel1.subCategories}" var="categoryLevel2">
// ...
<c:forEach items="${categoryLevel2.subCategories}" var="categoryLevel3">
// ...
</c:forEach>
// ...
</c:forEach>
// ...
</c:forEach>
<c:forEach var="rootCategory" items="${allCategories}" varStatus="rootCategoryLoop">
<c:if test="${rootCategory.rootCategoryId eq product.rootCategoryId}">
<c:forEach var="category" items="${rootCategory.categories}" varStatus="categoryLoop">
<c:if test="${category.categoryId eq product.categoryId}">
<c:forEach var="subCategory" items="${category.subCategories}" varStatus="subCategoryLoop">
<c:choose>
<c:when test="${subCategory.subCategoryId eq product.subCategoryId}">
<div>${subCategory.subCategoryName}</option>
</c:when>
<c:otherwise>
<div}">${subCategory.subCategoryName}</option>
</c:otherwise>
</c:choose>
</c:forEach>
</c:if>
</c:forEach>
</c:if>
</c:forEach>
I have limited subcategories level - to level 3.
So, this is the code in servlet:
// findAll() - returns all categories in database, as a list
List<Category> categories = categoryDao.findAll();
ServletContext servletContext = getServletContext();
servletContext.setAttribute("categories", categories);
And these are the loops in JSP page, where am i extracting data from list and generating html markup:
<li>Categories
<ul class="droprightMenu">
<li>All
<ul class="droprightMenu">
<!-- first loop, extracting categories level 1 -->
<c:forEach items="${categories }" var="catLevel1">
<c:if test="${catLevel1.getParentCategory()==null }">
<li>${catLevel1.getName() }
<!-- second loop, extracting categories level 2 -->
<ul class="droprightMenu">
<c:forEach items="${categories }" var="catLevel2">
<c:if test="${catLevel2.getParentCategory().getId()==catLevel1.getId() }">
<li>${catLevel2.getName() }
<!-- third loop, categories level 3 -->
<ul class="droprightMenu">
<c:forEach items="${categories }" var="catLevel3">
<c:if test="${catLevel3.getParentCategory().getId()==catLevel2.getId() }">
<li>${catLevel3.getName() }</li>
</c:if>
</c:forEach>
</ul></li>
</c:if>
</c:forEach>
</ul></li>
</c:if>
</c:forEach>
</ul></li>
</ul></li>
It is possible to bind a List of String (List) and display them in a jsp in a combo box like this:
<form:select path="countryId">
<form:option value="" label="Please Select"></form:option>
<form:options items="${countryList}" itemValue="countryId" itemLabel="countryName"/>
</form:select>
I want this list to display in <td> or <form:input> like fields, not in combo box.
I am binding String list in model as
Map referenceData = new HashMap();
referenceData.put("OutputsList", Outputs);
In JSP I use
<c:forEach var="OutputsList" items="${Outputs}">
${OutputsList}
</c:forEach>
But list is not printed. What could be the reason?
do it that way.
<c:forEach var="country" items="${countryList}">
<tr>
<td>${country.countryId}</td>
<td>${country.countryName}</td>
</tr>
</c:forEach>
and on the server side use ModelAndView object
List<Country> countryList;
ModelAndView mv = new ModelAndView("index");
mv.addObject("country",countryList);
There was a wrong approach while using it in a jsp. From the code in question just swap OutputsList
Map referenceData = new HashMap();
referenceData.put("OutputsList", Outputs);
In JSP I use
<c:forEach var="item" items="${OutputsList}">
${item}
</c:forEach>
It will work.