How to Set a HashMap from jsp to Action - java

I have a HashMap in my Action class:
private Map<String, String> ids = new HashMap<String, String>();
In jsp I'm trying to set this hashmap like this:
<input type="text" name="ids[0].key" value="key">
<input type="text" name="ids[0]" value="value">
But when after submit, when I iterate over the map in the action like this:
if(ids!=null){
for(Map.Entry<String, String> entry : ids.entrySet()){
system.out.println(entry.getKey()+"-"+entry.getValue());
}
}
I only get "0-value" instead of "key-value"
How Can I do what I want? Can someone help me with this?

Trying to set values in a HashMap in a JSP file is a very bad idea. To stick with best practice and lead a happy life, you should revisit your design. You can post the data to the server side (All input values from JSP) and then get the values from request to store in a HashMap collection as per your requirement would be a better option.

You have keys of type String and therefore should be mapped like strings. For example
<input type="text" name="ids['0']" value="%{value}">
Then you will get key '0' and value that was provided by OGNL.
About indexed property names and createIfNull setting you can find in the docs Advanced Type Conversion.

Related

How to compare hash map key dynamically inside the closure in Grails?

Here I have hash map passed from the controller to GSP page.
Controller:
Map<String, List<String>> nameFiles = new HashMap<String, List<String>>();
nameFiles.put('patient1',["AA","BB","CC"]);
nameFiles.put('patient2',["DD","EE","FF"]);
model.put("nameFiles", nameFiles);
GSP page:
var patient = getPatient(); // lets say we get random patient through some jQuery function, could be not available in the nameFiles key
//check If nameFiles contain key same as patient varaible
<% nameFiles.each { fm -> %>
<% if (fm.containsKey(patient)) { %> // This if statement cannot compare dynamic sting varaaible. How to do this.
alert("Yes nameFiles contain the patient");
<% } %>
<% } %>
Assuming you have :
Map<String, List<String>> nameFiles = new HashMap<String, List<String>>();
nameFiles.put('patient1',[id:1,name:'Fred'])
nameFiles.put('patient2',[id:2,name:'Tom'])
It is as simple as this to get current patient:
<% def aa = nameFiles?.find{it.key=='patient1'}?.value %>
<g:if test="${aa}">
// we definitely have ${aa} and it has been made null safe
<g:if>
This returns {id:1, Name:Fred} on gsp which is the list iteration
My goodness all that else if it is as if you are in a controller, I understand why you are having to do this but it isn't good practice you could just create a tagLib that takes current value and processes the entry according to something in a given list or maybe against db fresh on the fly all correctly presented produced.
Final edit whilst you can declare variables like jsp you can also use
<g:set var="aa" value="${nameFiles?.find{it.key=='patient1'}?.value}" scope="page|session|..."/>
By default variable is set for the page but could be made into a session variable either way it is a lot cleaner than <% %>
Hopefully final edit
I think people should think carefully about what their actual problem is and try to present the problem clearly otherwise the audience ends up answering something else due to the poor quality of the post.
If I understand correctly you have something happening in a controller as in some list being produced. The missing bit must be you are then doing some form of form check maybe a select box selection that then ends up in jquery by that you mean you have some form of java script check going on against a form field check.
There are two ways of pumping such information into the javascript world for such purposes
Method 1:
//I haven't tested this, hopefully gives you the idea
var array = []
<g:each in="${namedFiles}" var="${pa}">
array.push({code:'${pa.key} listing:'${pa.value}'})
</g:each>
Method 2
Controller
//where you now push named files as a json
return [namedFiles as JSON].toString()
// or alternatively in gsp javascript segment something like this
var results=$.parseJSON('<%=namedFiles.encodeAsJSON()%>');
var results = results['patient1']
Honestly speaking I didn't get what are you asking and what kind of problem do you have as a result, but I guess that you tried to implement something like that:
<g:if test="${nameFiles[patient]}">
alert("Yes nameFiles contain the patient");
</g:if>
As you may be noticed I tried to avoid the scriptlet mess and used grails custom tags.
Also I hardly imagine how are you going to call the jQuery function to get a variable and then use it for generating a view on the server side. But try to define some mock "patient" variable at first to test my sample.
If the "patient" variable value is only available at the client side - so you have to change the approach and generate your alerts not on the server.
UPD
From the other hand you could return your nameFiles as JSON in your controller and then parse this JSON with javascript on the client side like that:
var nameFiles = JSON.parse("${nameFiles}")
if (nameFiles.hasOwnProperty(patient)) {
alert("Yes nameFiles contain the patient");
}
I haven't test this code, but at least you are pointed that gsp are rendered on server and you can convert your map to JSON, pass it to the view, parse with JavaScript and generate the needed alert.
Variable Declaration in GSP
You can declare variables within <% %> brackets:
<% patientIdentifier = 'randomName' %>
For more details see the Grails documentation on Variables and Scopes.
Checking if Patient is contained in namedFiles
You don't need to iterate over the map. Just checking the map if it contains the key.
// check if nameFiles contains key same as patient variable
<% if (nameFiles.containsKey(patient)) { %>
alert("Yes nameFiles contains the patient");
<% } %>

Spring Mvc display data from multiple Lists in Jsp

Hi there I am using Spring MVC and I am trying to display some data from multiple Lists in a jsp page. I've searched and found some similar topics but I wasn't able to achieve what I am trying to do plus got more confused.
My model class contains something like this:
private String BlaBla1;
private String BlaBla2;
private List<String> Alpha;
private List<String> Beta;
.....
//getters setters
What I want is to display a table in a jsp with the values from these two Lists (Alpha and Beta ..) one value at a column.They both have the same number of values.
For Example
<tr><td>Alpha.value1</td><td>Beta.value1</td></tr>
<tr><td>Alpha.value2</td><td>Beta.value2</td></tr>
......................................
<tr><td>Alpha.valueN</td><td>Beta.valueN</td></tr>
As I've seen here rendering data in jsp using spring controllers and different classes
and some other examples, they create something like that: List<MyObjects> objects but MyObjects model always has private String ... and NOT any List<String>..
I tried to construct something like that
Map<String,List<String>> test = new HashMap<String,List<String>>();
then
test.put("alfa", Alpha);
test.put("beta", Beta);
but all I got was just display them in 2 rows and a single column using
<c:forEach var="testValue" items="${test}">
<tr><td>${testValue.value}</td></tr>
</c:forEach>
Please don't aske me to change my Model class, it is 'impossible'.
I've seen somewhere saying to use Collection but I'm not sure how to do that.
Any suggestion would be useful,
happy coding!
model.addObject("alphaList", alpha);
model.addObject("betaList", beta);
In the jsp :
<c:forEach var="listItem" items="${alphaList}" varStatus="theCount" >
<tr><td>${listItem}</td><td>${betaList[theCount.index]}</td></tr>
</c:forEach>
Note : ${theCount.index} starts with 0
${theCount.count} starts with 1.
So basically you can use the count to iterate over the second list.
You just have to iterate the Alpha list normally ... but with use of the varStatus attribute of <c:foreach > tag. This varStatus has (among others) an attribute index which is the index of the iteration and all what you need to display corresponding element from Beta list. Code example :
<c:forEach var="alphaVal" items="${Alpha}" varStatus="status">
<tr><td>${alphaVal}</td><td>${Beta[status.index]}</td></tr>
</c:forEach>

How to use an HTML5 data attribute to get session attribute

I'm new to the front end side of Java EE and HTML5. I have read that you could use the data attribute to read through the DOM. How would you properly use this to get a session attribute already set by java. Compared to the other methods such as using a hidden input.
<input id="sid" type="hidden" name="series" value="${sessionScope.series} />
var sid = document.getElementById("sid"), series;
Use something like this:
<div id="div1" data-special-value="${sessionScope.series}"></div>
And get the attribute value like:
document.getElementById("div1").getAttribute("data-special-value")
Or even ( http://caniuse.com/dataset ):
document.getElementById("div1").dataset("special-value")
Or with jQuery:
$("#div1").attr("data-special-value")
// or
$("#div1").data("special-value")
Although I'm not sure storing a session value on an element is right. It's definitely not wrong, I'm just wondering what you'd need/use it for with sessions. Sessions appear once.
The data-* attributes are more useful with storing related data to something. For example, if you loop through a bunch of database records and print their columns, but want to also store the row's database id once, you'd use:
<c:forEach items="${rows}" var="row">
<tr data-row-id="${row.id}">
<td>${row.name}</td>
<td>${row.description}</td>
</tr>
</c:forEach>
Then if you want to get the original row.id value, it's stored in one place an encompasses everything it pertains to (the columns). This is usually how/where I use data-* attributes. Of course, there are many ideas/uses for this.

How do I retrieve the values of checkboxes when the Id values are dynamically generated

I am dynamically naming a set of checkboxes based on certain files names (user is selecting file to include for some processing).
Is there a way I can retrieve the files names or do I need to save them to a session object of some sort and then use the retrieved values (from the session object) to retrieve the values of the checkboxes.
In short what I really want is to know which checkboxes have been clicked and which file names they correspond to, any solution will be fine.
Use unique id, but same name. Then you will be able to use either getParameterValues(name), or getParameterMap() of ServletRequest. Remember, you will only get what is selected.
Are you doing all this server side or using java-script client side?
If it's all server side, why not prepend checkbox on the name when you dynamically name them:
<input type="checkbox" name="checkbox_someRandomeName" value="something" />
You can then loop the posted variables and see if the name starts with "checkbox":
ParameterMap paramMap = request.getParameterMap();
// Loop through the list of parameters.
Iterator y = paramMap.keySet().iterator();
while (y.hasNext()) {
String name = (String) y.next();
if name.startswith("checkbox"){
// do something
}
}
What does your HTML look like? I'd expect checkboxes like:
<li><input id='0001' type='checkbox' name="files[]" value="file1"/>/xyz/file1</li>
<li><input id='0002' type='checkbox' name="files[]" value="file2"/>/xyz/file2</li>
<li><input id='0003' type='checkbox' name="files[]" value="file3"/>/xyz/file3</li>
<li><input id='0004' type='checkbox' name="files[]" value="file4"/>/xyz/file4</li>
The name will be associated with any values checked on submit. Here, I used files[] because that's required by PHP, I haven't done this in servlets.

how to submit a form that will have dynamically (unknown) number of fields

I am trying to submit a form to a servlet (java). The form has a bunch of questions, each question has 4 radio buttons and the user selects one of them. I do not know the number of questions that will be in the form. It could be 10, 15, 12...depends on some other criterias. My question is what is the best way to retrieve the list of choices that the user made for the questions on the form.
You can use HttpServletRequest.getParameterNames() to retrieve an Enumeration of names of all form elements within the request. You can then iterate over the enumeration and request individual value for each element using HttpServletRequest.getParameter(name).
If your HTML contains other FORM elements other than your option radio buttons, use clever naming convention of these radio button so that while enumerating over the parameter names, you know what to request.
An example.
If your form contains two questions with following options:
Question 1:
<input type="radio" name="question1" value="option1">
<input type="radio" name="question1" value="option2">
<input type="radio" name="question1" value="option3">
Question 2:
<input type="radio" name="question2" value="option1">
<input type="radio" name="question2" value="option2">
<input type="radio" name="question2" value="option3">
In your servlet,
Enumeration e = request.getParameterValues();
while(e.hasMoreElements()){
String name = (String)e.nextElement();
if(name.startsWith("question"){
String value = request.getParameter(name);
//your logic here
}
}
Another of doing the same is:
In your servlet,
int maxQuestionNumber = Integer.parseInt(request.getParameter("maxQuestionNumber"));//this should be a hidden variable in your HTML form representing the max questions in your form.
for(int i=1;i<=maxQuestionNumber;i++){
String value = request.getParameter("question"+i);
//your logic here..
}
A quick trick that comes to my mind is to name all the fields as
"question_"+n
And have a input type hidden with the value of n. If the form has a way to know how many question to present, it should have a way to set the value of n.
Later you just retrieve that value and ...
n = new Integer( request.getParameter("number_of_question"));
for( int i = 0 ; i < n ; i++ ) {
list.add( request.getParameter("question_"+i));
}
This is the first thing that comes to my mind
I would suggest no workarounds. the ServletRequest.getParameterMap() would come handy in this scenerio. The keys of the map would be of type String, and the values will be of type String[].
Hence, you can very easily loop through the map using foreach loop something like this,
for(Map.Entry<K, V> entry : map.entrySet()){
..
if(entry.getValue().length > 1){
//means the choices not the question
}else{
//means the question not the choices
}
}
I hope it would help.
A typical technique is to name the fields with a common prefix, and then iterate through them: q000, q001, q002, etc., until you reach one that's not present.
You could just use JSON, and so pass a string to the servlet, which can handle a very long string if you use POST. That way you can pass whatever you want, even if the parameters are complex.

Categories

Resources