I want to iterate a HashMap in javascript using jstl. is it possible to do like this?
function checkSelection(group,tvalue){
alert(group);
alert(tvalue);
<c:forEach items="${configuredGroupMap}" var="groupMap">
alert("aa<c:out value="${groupMap.key}"/>");
<c:if test="${groupMap.key==group}">
alert("t<c:out value="${groupMap.key}"/>");
<c:if test="${groupMap.value==tvalue}">
alert("equal");
</c:if>
</c:if>
</c:forEach>
}
it's not going inside after
<c:if test="${groupMap.key==group}">
"to iterate a HashMap in javascript using jstl" - Not possible
JSTL is executed in server side by your servlet container for which Javascript is just a text which would be skipped whereas JavaScript is executed in client side where JSTL is unknown. After the server completes processing JSTL, the generated HTML(if any) from the JSTL along with other JavaScript/HTML will be rendered.
For example, if you have this,
<c:forEach var="myItem" items="${myCollection}">
alert('<c:out value="${myItem.id}">')
<c:if test="${myItem.id == 0}">
alert("zero");
</c:if>
</c:forEach>
If the ids of the beans in the collection are 0, 1, 2, the server renders the following to the client side by executing the above code,
alert('0')
alert('zero')
alert('1')
alert('2')
Now the browser will give you 4 alerts on loading the page (what if you have 10000 items, you will render 10000 alert statements to the browser). So the point is that you haven't iterated Java collection in JavaScript, you have simply generated a serious of Javascript statements in server iterating the collection using JSTL and you have provided those Javascript statements along with other html contents to browser.
It is not possible because JSP is executed first at the server side, then the JavaScript gets executed at the client side.
You can still use the c:forEach to loop through the ${configuredGroupMap}, but you cannot do the comparison across groupMap.key and group directly.
Instead, a solution in this case is to assign the server-side groupMap.key to a client-side variable in javascript first. Then use javascript for the if check, instead of c:if.
I've modified your example to below
function checkSelection(group,tvalue){
alert(group);
alert(tvalue);
<c:forEach items="${stringshm}" var="groupMap">
alert("<c:out value="${groupMap.key}"/>");
var groupKey = "<c:out value="${groupMap.key}"/>";
if (groupKey == group){
alert("<c:out value="${groupMap.key}"/>");
var groupValue = "<c:out value="${groupMap.value}"/>";
if (groupValue == tvalue){
alert("both are equal");
}
}
</c:forEach>
}
Marimuthu has nailed it down. JavaScript and JSP/JSTL doesn't run in sync as you'd expect from the order in the coding. Java/JSP processes the page from top to bottom first, then the webserver sends the HTML/CSS/JS result to the webbrowser and finally the webbrowser processes the page (not containing any line of Java/JSP!) from top to bottom.
The best solution is to let JSP/JSTL generate a JavaScript object variable which you can later access in the JS code.
var groupMap = {
<c:forEach items="${configuredGroupMap}" var="groupMap" varStatus="loop">
"${groupMap.key}": "${groupMap.value}"${!loop.last ? ',' : ''}
</c:forEach>
};
This will end up like the following in client side (rightclick page and View Source to be sure)
var groupMap = {
"key1": "value1",
"key2": "value2",
"key3": "value3"
};
Finally rewrite checkSelection() as follows:
function checkSelection(group, tvalue) {
if (groupMap[group] == tvalue) {
alert("equal");
}
}
See also:
Communication between Java/JSP/JSF and JavaScript
Essential JavaScript tutorial
JSON (JavaScript Object Notation) tutorial
Related
So, I am trying to pass a Set into a .jsp page using Spring and JSP EL, and then assign the members of the set to a Javascript array to use later in client-side scripts.
For example, if I have the Java Set
exampleSet: { "A", "B", "C"}
I pass it to the client side as part of a spring ModelandView object.
In the client-side JSP, I can use EL to output the set as
${model.exampleSet}
, which gets parsed into [A, B, C] by JSP.
What I want to do is assign the contents of exampleSet to an array of javascript strings, so you get something like
var exampleSet = ["A", "B", "C"]
I can't find a direct way to do this. The other obvious approach to this is to loop through the Set, but as I can't work out the size of the Set in javascript, I don't think I can do this either.
JavaScript executes on the browser. The JSP is rendered on the server. You're missing the lifetimes of the execution environments here.
What you would do is
<script>
var exampleSet = [
<c:forEach var="item" items="${theSetVariable}" varStatus="loop">
"${item}"
<c:if test="${!loop.last}">,</c:if>
</c:forEach>
]
<script>
So, you're looping through the Set in the JSP, to create the HTML/JavaScript, that creates code to represent the Javascript array when rendered on the browser.
I have a list of notification messages which I extract from the databse and put in the session in a servlet. This is then forwarded to a jsp page using requesDipstacher.forward(request,response). I now take the List of messages and loop it through using jstl :
<c:foreach value = "item" items = '${sessionScope.notification}'>
<a href = "javascript:printAll('${item}'}>Print</a>
</c:foreach>
The javascript looks like this
function printAll(item)
{
display(item) //note this is pseudo code . Here I kind of display the items.
}
Now my problem is there are far too many links displaying print in my webpage. I want to send the whole list into the javascript and iterate over it and display the individual messages. Is this possible with javascript.Kindly point me to an identical question if it exists.
If you don't have problem with put the javascript in the same file of the page, you could put something like this:
<script>
function printAll()
{
var html = '<ul>';
<c:foreach value = "item" items = '${sessionScope.notification}'>
html += '<li>${item}</li>';
</c:foreach>
html += '</ul>';
display(html);
}
</script>
Print
As you notice it, there are various ways to solve the problem.
This question already has answers here:
Access Java / Servlet / JSP / JSTL / EL variables in JavaScript
(5 answers)
Closed 5 years ago.
I have a dropdown box in JSP, listing a Java object (accessing the object through the MVC controller's addAttribute). Now, on selection of an option from the dropdown box, I would like to display the selected employee's other details (example - ${employee.employeeCV}, ${employee.employeeName}) in a div. I have a JavaScript function for that (displayCV()). But I am not sure how to do this.
JSP -
<c:forEach items="${employees}" var="employee">
<option value="${employee.id}" onclick="displayCV();">
${employee.employeeName}
</option>
</c:forEach>
<b>CV:</b>
JavaScript
function displayCV() {
var valueSelected = $('#employeeList').val();
var div = $('#candidateDiv');
}
How can I do this?
You can't access Java classes directly from JavaScript. You have to use some kind of web service communication between the JavaScript (client) and Java (server). You can make use of the onchange event which will send a request to the server to return XML/JSON which you can parse to get the data (I see you're using jQuery, and it has parseJSON method already) and update the corresponding node in the DOM.
Another easier way, though, that is not multi-user friendly (because it can't detect updates) is to "convert" the Java object to JavaScript and update the data using that object (still using onchange). Something like:
// This is JavaScript code written in the JSP
var employees = {
<c:forEach items="${employees}" var="employee">
"${employee.id}": {
name:"${employee.employeeName}",
cv:"${employee.employeeCV}",
},
</c:forEach>
}
Now when JSP parses this, it would generate, for instance:
var employees = {
"1": {
name:"foo",
cv:"cv1",
},
"2": {
name:"bar",
cv:"cv2",
},
}
Meta of what LeleDumbo said here already:
First, you must understand that JSP is a server-side view technology, whereas JavaScript typically runs on the client (browser).
Now, how you solve the problem in hand. So, you can make an Ajax request from your JavaScript code, which will fetch you the data in JSON/XML format. Then, you can present that data in the browser using JavaScript.
Further reading: jQuery Ajax API and code samnple snippets
Call the function on the onchange event of select instead of onclick of options. And use:
document.getElementById('GrdDamagedstock_tplRowEdit_ctl00_cmbFromBin').options[ele.options.selectedIndex].innerHTML;
to get the selected value.
Traditionally we have always used xml in the response which is parsed by a Javascript method to execute post processes. I came up with a new, simpler implementation which uses a hidden input set by a requestAttribute and executed in an ajax callback.
JSP:
<%
String jsPostProcess = (String)request.getAttribute("jsPostProcess");
if (jsPostProcess!=null && jsPostProcess.trim().length()>0){
%>
<input type="hidden" id="jsPostProcess" name="jsPostProcess"
value="<%= jsPostProcess %> "/>
<% } %>
AJAX CALLBACK:
var callback = {
success: function(response) {
var div = $(divId);
if (div){
div.innerHTML = response.responseText;
}
var jsPostProcess = $('jsPostProcess');
if (jsPostProcess)
eval(jsPostProcess.value);
},
failure: function(response) {
alert('Something went wrong!');
}
}
SERVLET CODE:
request.setAttribute("jsPostProcess", jsPostProcess);
It works beautifully, and it is so much simpler for adding js post processes to virtually any call no matter how simple or complex the functionality is. No need for customized js methods for parsing.
Curious if anyone could identify any potential problems with it (such as security issues?) or make any suggestions for other alternatives. We currently use Prototype and YUI 2 on the front-end.
First, there's no need for that unpleasant scriptlet code:
<c:if test='${not empty jsPostProcess}'>
<input type='hidden' id='jsPostProcess' name='jsPostProcess' value='${jsPostProcess}'>
</c:if>
Next thing is that I hope that somewhere before this point the "jsPostProcess" value has been scrubbed so that it doesn't break the markup (like, in case it includes quotes).
Just calling eval() on the value like that seems a little dangerous, though perhaps you know pretty well what it's going to be.
Finally I would offer the suggestion that as an alternative to that, if the "post process" code isn't too big you could send it back in a response header. Then you wouldn't have to drop any meaningless markup into your page.
Oh, also finally: you might want to make the <input> be disabled. Or, alternatively, you don't even have to use an input: you can use this trick:
<script id='jsPostProcess' type='text/plain'>
${jsPostProcess}
</script>
Because the "type" attribute is "text/plain" the browsers won't try to execute that code, and you can get the "text" of the <script> element whenever you want.
I have the following simple script, which I am using to dynamically create the list elements in a <ul>
<script type="text/javascript">
function generate(){
var arr = new Array();
<c:forEach items="${articles}" var="a" varStatus="status">
$('#listitems').append(
"<li>"+${a.title}+"</li>"
);
arr[${status.index}] ="${a.slideShow.images}";
</c:forEach>
}
</script>
My problem stems from the images attribute. Every article has a slideshow and every slideshow has a list of images. I want to pull out the very first image from the list of images via the jave list.get(index); I want to do something like "${a.slideShow.images.get(0)}";. The get() is a java method from the list object.
Any ideas?
In EL you can use the brace notation to access a List element by index. Thus, the following should do:
arr[${status.index}] = "${a.slideShow.images[0]}";
This will behind the scenes do exactly as you proposed: a.getSlideShow().getImages().get(0).
That said, you normally declare JS arrays like follows:
var arr = [];
The new keyword is considered discouraged in JS.
As those who commented on your question suggest, this is a common misunderstanding. By the time your JavaScript executes (in the browser), Java and JSP and JSTL are no longer available. The JSTL/JSP execute at the server to create source/HTML that is then sent to the client.
View source on your page - it might shed some light. You should not see the JSP/JSTL you include above.