Pass java map from JSTL/JSP to JavaScript methods - java

We have couple of related drop downs where results of one drop down relate to other dropdown.
We have a mapping defined for what to select when in the form of map-of-map, like this;
Map<String,Map<String,String>> topics = new HashMap<String, Map<String,String>>();
Map<String,String> ds = new HashMap<String, String>();
ds.put("Array", "Array");
ds.put("LL", "LL");
topics.put("DS", ds);
Map<String,String> algo = new HashMap<String, String>();
algo.put("BS", "BS");
algo.put("Sorting", "Sorting");
topics.put("Algorithm", algo);
Map<String,String> phil = new HashMap<String, String>();
phil.put("phil1", "phil1");
phil.put("phil2", "phil2");
topics.put("Philosophy", phil);
Map<String,String> others = new HashMap<String, String>();
others.put("others", "others");
topics.put("Others", others);
As per the above map, when "DS"is selected, we want to display "Ă„rray"and "LL". Similar is the case with other mappings.
I pass this map to JSP and use JSTL to render the options. While making decision to call JS to populate subsequent drop-down, I want to change it to JSON.
I want to pass specific map of the selected option to the JS method and populate subsequent drop down.
Is converting to JSON the only way? If yes, how about passing it from the controller? If we don't pass it from the controller, what are the cleaner ways to do it in JSP itself?
JSP Block is as follows:
<div>Subject</div>
<select name="topic" onchange="callJavaScriptMethodWithMapOfSelectedComponent(mapOfSelectedValue)");">
<c:forEach var="entry" items="${topics}">
<option value="${entry.key}">${entry.key}</option>
</c:forEach>
</select>
<select name="college">
<option value="default">Select Subject</option>
</select>
Depending on the values selected in first drop down, we need to populatevalues in second drop down.
JS method would take map of selected value in first drop down and populate second one.
function setOptions(chosen) {
var selbox = document.myform.college;
selbox.options.length = 0;
if (chosen == " ") {
selbox.options[selbox.options.length] = new Option('Please select one of the options above first',' ');
}
selbox.options[selbox.options.length] = new Option('//Choosen from the map passed','oneone');
}
}

First off I think you better change it so that topics is a Map < String, List < String > >, that'd make more sense since it's a single depth hierarchy.
Next up you have the choice of either converting the map into JSON and using eval to fill an object in javascript, or manually transverse the map keys and add them to the object, it all depends on the tools you have at hand to serialize the map into JSON server side (You can use new JSONObject(topics); from json.org) then just eval the json into a variable on Javascript.

Related

Populating HashMap with for loop in java

I'm trying to populate LinkedHashMap with for loop in order to use it in my jsf page but "put" method of hashmap overwrites the values that is held in hashmap when the new "put" method is fired.
The method is like that;
public static List<String> valuesOfEnum() throws JsonProcessingException {
Map<String, Object> newArray = new LinkedHashMap<String, Object>();
List<String> jsonObj = new ArrayList<String>();
String json = null;
for(LimanTipi limanTipi : values()){
newArray.put("id", limanTipi.getId());
newArray.put("value", limanTipi.getValue());
json = new ObjectMapper().writeValueAsString(newArray);
jsonObj.add(json);
}
return jsonObj;
}
Here's the jsf code;
<f:selectItems value="#{denizlimaniViewController.limanTipleri}" var="limanTipleri" itemValue="#{limanTipleri.id}" itemLabel="#{limanTipleri.value}"/>
With this method, I convert the hashmap into list as I couldn't populate the hashmap properly but this is not what I want because I can't use this list in <f:selectItems>.
I need to use itemValue and itemLabel representing "id" and "value" properties in hashmap.
Is there a way to handle this?
Thanks
Key get's overwritten because you always have keys as id and value. Modify your code like below:
for(LimanTipi limanTipi : values()){
newArray.put(limanTipi.getId(), limanTipi.getValue());
json = new ObjectMapper().writeValueAsString(newArray);
jsonObj.add(json);
}
EDIT:
Hope limanTipleri is the map newArray itself. Then you need to modify your code like below:
<f:selectItems value="#{denizlimaniViewController.limanTipleri.entrySet()}"
var="limanTipleri"
itemValue="#{limanTipleri.key}" itemLabel="#{limanTipleri.value}" />

Getting NoFastSuchElementException, when I use valueMap() in gremlin query with java

GraphTraversal<Vertex, Map<String, Object>> tsList = traversalSource.V().has("request","id_key",114).valueMap();
while(tsList.hasNext())
{
System.out.println(tsList.next().get("status")); //prints result
System.out.println(tsList.next().get("tree_id_key")); //prints result
System.out.println(tsList.next().get("username")); //here throws Exception for any vertex.
System.out.println(tsList.next().get("tree_status"));
}
when I run the above query, I am getting values for any first and second propertyKey. but after getting answers for two Keys It throws NoFastSuchElementException for any propertyKey...Kindly help me..how can I resolve this?
but using below query I am able to get the answer:
GraphTraversal<Vertex, Map<String, Object>> tsList = traversalSource.V().has("request","id_key",114).values("status","tree_id_key","username","tree_status");
while(tsList.hasNext())
{
System.out.println(tsList.next());//prints "status" value
System.out.println(tsList.next());//prints "tree_id_key" value
System.out.println(tsList.next());//prints "username" value
System.out.println(tsList.next());//prints "tree_status" value
}
updated:
GraphTraversal<Vertex, Map<String, Object>> ts = traversalSource.V().has("request","id_key",113).valueMap();
while(ts.hasNext())
{
Map<String, Object> tsList=ts.next();
SuiteIdKey=(long)((ArrayList)tsList.get("suiteKey")).get(0);
seqe=(int)((ArrayList)tsList.get("sequence")).get(0);
}
In the above query, ts will return many rows and for each row I will get suiteIdkey,seqe..I am able to get the answer. But tsList is Map<>, it is not directly returning answer when I use like this =(long)tsList.get("suiteKey"), without ArrayList. Is it the correct way? Kindly help me.
You are asking for two different things in those two traversals. The first one with valueMap() asks that the vertex be converted to a Map, so you don't want to keep calling next() in that loop. Just do:
Map<String, List<Object>> m = traversalSource.V().has("request", "id_key", 114).
valueMap().next();
System.out.println(m.get("status").get(0));
System.out.println(m.get("tree_id_key").get(0));
System.out.println(m.get("username").get(0));
System.out.println(m.get("tree_status").get(0));
Keep in mind above that i'm assuming your traversal always returns one vertex...account for that otherwise if that is not true.
In your second traversal where you do values() you are asking Gremlin to convert grab the values of those specific properties on that vertex and stream them out and thus you need to iterate with multiple calls to next.
Note that typically returning the entire vertex object isn't a recommended practice. It is somewhat akin to SELECT * FROM table in SQL. It is better to get only the fields that you want to get which then gets rid of the ugly multi-property issue of Map<String, List<Object>>:
Map<String, Object> m = traversalSource.V().has("request", "id_key", 114).
project('s`,'tik', 'u', 'ts').
by('status').
by('tree_id_key').
by('username')
by('tree_status').
next();
System.out.println(m.get("s"));
System.out.println(m.get("tik"));
System.out.println(m.get("u"));
System.out.println(m.get("ts"));

How to iterate list inside a map in ftl?

I have two value objects and i have to write a file using free marker while i am writing it using simply java i am able to iterate the list but don't know how to iterate a map whick consist a variable as well as a list. in my one value object BranchArea i have variable like name and id and a list of Branch. Branch is another value object who as a variable like name etc. i am iterating in java like this
List <BranchArea> branchAreaList = new ArrayList<BranchArea>();
Iterator<BranchArea> itrBranchArea = branchAreaList.iterator();
while (itrBranchArea.hasNext()) {
BranchArea branchAreaObj = itrBranchArea.next();
LOGGER.error("Branch Area Name is"+branchAreaObj.getBranchAreaName());
Iterator<Branch> itrBranch = branchAreaObj.getBranches().iterator();
while(itrBranch.hasNext()){
Branch branchObj = itrBranch.next();
LOGGER.error("Branch Name is"+branchObj.getBranchName());
}
}
branchAreaList Consist object of BranchArea. For Ftl i convert the branchAreaList into map
HashMap<String, List<BranchArea>> branchAreaMap = new HashMap<String, List<BranchArea>>();
branchAreaMap.put("branchAreaList", branchAreaList);
How can i iterate them in Ftl as i iterate it above
You can iterate over keys of your Map, and get the elements by this way:
<#list branchAreaMap?keys as key>
${key} = ${branchAreaMap[key])}
</#list>

Sorting Select Option in Javascript - Based on multiple values in same row

I have created a list box like this, and created a title bar which helps to sort data:
ID Name
------------------------------------------------------------
ID1 Identity One
ID2 Identity Two
ID3 Identity Three
ID4 Identity Four
-------------------------------------------------------------
I have a requirement to sort above list based on ID and also on Name, means when user clicks ID, it should sort list based on ID and vice versa. But the problem is from data layer we are getting like this in a single line:
ID1 &nbsp:Idenitity One
So we are printing the same in options tag, and getting output like above. Code to generate above output is:
<select id="selSort" size="10" style="width:350px" id="rpt">
<option value = "ID1">
ID1 Identity One
</option>
<option value = "ID2">
ID2 Identity Two
</option>
<option value = "ID4">
ID4 Identity Four
</option>
<option value = "ID3">
ID3 Identity Three
</option>
My question is how do I implement sorting facility for above scenario? Yes, I tried to sort, but it is sorting entire list box, not based on single value. At-least now what can I do is format incoming data such way that put all Ids in one array and names in another, so any guide/pointers on this appreciated. Please let me know if I haven't explained clearly
EDIT:
Code I tried to sort a list box
function sortSelect(selElem) {
var tmpAry = new Array();
for (var i=0;i<selElem.options.length;i++) {
tmpAry[i] = new Array();
tmpAry[i][0] = selElem.options[i].text;
tmpAry[i][1] = selElem.options[i].value;
}
tmpAry.sort();
while (selElem.options.length > 0) {
selElem.options[0] = null;
}
for (var i=0;i<tmpAry.length;i++) {
var op = new Option(tmpAry[i][0], tmpAry[i][1]);
selElem.options[i] = op;
}
return;
}
You can use the custom array sort take a look at this How to sort select base on an id ?
The idea here is just create a arrray and sort that based on its value and than dynamically create the option based on the sorted value.
Custom sorting code
source.sort(function (x, y) {
if (isAsc)
return y.id - x.id;
else
return x.id - y.id;
});

Return HashMap in mybatis and use it as ModelAttribute in spring MVC

I want to display list of categories in my Jsp page using spring mvc #modelAttribute.
In my mapper.xml file is
<select id="selectAllCategories" resultMap="BaseResultMap">
select id, name from categories
</select>
In my Mapper.java class I have method
List<Map<String, String>> selectAllCategories();
I want to have a method like this:
Map<Integer, String>`selectAllCategories();
instead of List<Map<>>, is that possible?
You want to get a Map<Integer,String> where the Integer is the id and the String is the name. If there were 200 categories in your table, you would want 200 entries in your map, rather than a list of 200 maps.
MyBatis can't quite do that out of the box, but you can use its facilities to do that. I see two options.
Option 1:
The first isn't quite what you asked for but is worth showing. It gives you a Map<Integer,Category> where Category is a domain object for the categories table that has id, name (and possibly other fields from the categories table). After you've created the Category domain object, this is quite easy to do in MyBatis using the #MapKey annotation:
#Select("SELECT id, name FROM categories")
#MapKey("id")
Map<Integer,Category> getAllCategories();
In your code you would then do:
MyMapper mapper = session.getMapper(MyMapper.class);
Map<Integer,Category> m = mapper.getAllCategories();
That may or may not work for your use case depending on whether whether you can extract the name as a property of the Category object.
Option 2:
To get the Map<Integer,String> you asked for, the easiest way I know is to create a class that implements the MyBatis ResultHandler interface.
Your ResultHandler will use the default hashmap of column-name => column-value that MyBatis creates and create a single master Map. Here's the code:
public class CategoryResultHandler implements ResultHandler {
Map<Integer,String> inMap = new HashMap<Integer,String>();
public Map<Integer, String> getIdNameMap() {
return inMap;
}
#Override
public void handleResult(ResultContext rc) {
#SuppressWarnings("unchecked")
Map<String,Object> m = (Map<String,Object>)rc.getResultObject();
inMap.put((Integer)getFromMap(m, "id"),
(String)getFromMap(m, "name"));
}
// see note at bottom of answer as to why I include this method
private Object getFromMap(Map<String, Object> map, String key) {
if (map.containsKey(key.toLowerCase())) {
return map.get(key.toLowerCase());
} else {
return map.get(key.toUpperCase());
}
}
}
The handleResult method gets called once per row in the category table. You tell MyBatis to use the ResultHandler and then extract your master map like this:
CategoryResultHandler rh = new CategoryResultHandler();
session.select("getAllCategories", rh);
Map<Integer,String> m = rh.getIdNameMap();
One of those two should work for you.
A few final notes:
Why did I include the getFromMap() helper method? Because you can't always control the case of the column name in the hashmap that MyBatis returns. More details here: mybatis- 3.1.1. how to override the resultmap returned from mybatis
I have working examples of these solutions in Koan26 of the mybatis-koans (which I added based on your question): https://github.com/midpeter444/mybatis-koans

Categories

Resources