How do I pass a JSON object from JSP to Javascript? - javascript

I have a variable for myInitState that is initialized within a controller that is then passed to a jsp view.
<script>
myInitFunction({
myInitState: '${myInitState}',
componentName: 'myCompName',
divId: 'divId'
});
</script>
However by using '${myInitState}', in my Javascript I notice I get a string of "{...}" when debugging in browser. Is it possible to pass the object as json and have it be recognized as such or would I have re-parse the object within myInitFunction?

In order to take advantage of string interpolation, you need to use backticks
`${myInitState}`
You will then want to parse the string inside the function using JSON.parse(someString)

Updating answer here:
A couple of things I had left out of my question due to my misunderstanding:
- myInitState is a Map of <String,Object>
- The values of the map could be already escaped JSON blobs.
In this case the flow was from Server to client, so in order to convert the map into a JSON blob correctly I would need to do something like this in JSP:
<script>
var jsonBlob = {
<c:forEach items="${myInitState}" var="state" varStatus="loop">
"${state.key}": ${state.value} ${not loop.last ? ',' : ''}
</c:forEach>
};
</script>
However, a better approach, and what I went with, would be to just do conversion in the controller itself where myInitState is constructed.

Related

JavaScript - How to evaluate an EL with a JS variable inside? [duplicate]

I have a form in JSP. I have to populate it based on the request object (from the servlet). How do I use Java Script for accessing request object attributes or if you can suggest me any other better way to populate form dynamically?
You need to realize that Java/JSP is merely a HTML/CSS/JS code producer. So all you need to do is to just let JSP print the Java variable as if it is a JavaScript variable and that the generated HTML/JS code output is syntactically valid.
Provided that the Java variable is available in the EL scope by ${foo}, here are several examples how to print it:
<script>var foo = '${foo}';</script>
<script>someFunction('${foo}');</script>
<div onclick="someFunction('${foo}')">...</div>
Imagine that the Java variable has the value "bar", then JSP will ultimately generate this HTML which you can verify by rightclick, View Source in the webbrowser:
<script>var foo = 'bar';</script>
<script>someFunction('bar');</script>
<div onclick="someFunction('bar')">...</div>
Do note that those singlequotes are thus mandatory in order to represent a string typed variable in JS. If you have used var foo = ${foo}; instead, then it would print var foo = bar;, which may end up in "bar is undefined" errors in when you attempt to access it further down in JS code (you can see JS errors in JS console of browser's web developer toolset which you can open by pressing F12 in Chrome/FireFox23+/IE9+). Also note that if the variable represents a number or a boolean, which doesn't need to be quoted, then it will just work fine.
If the variable happens to originate from user-controlled input, then keep in mind to take into account XSS attack holes and JS escaping. Near the bottom of our EL wiki page you can find an example how to create a custom EL function which escapes a Java variable for safe usage in JS.
If the variable is a bit more complex, e.g. a Java bean, or a list thereof, or a map, then you can use one of the many available JSON libraries to convert the Java object to a JSON string. Here's an example assuming Gson.
String someObjectAsJson = new Gson().toJson(someObject);
Note that this way you don't need to print it as a quoted string anymore.
<script>var foo = ${someObjectAsJson};</script>
See also:
Our JSP wiki page - see the chapter "JavaScript".
How to escape JavaScript in JSP?
Call Servlet and invoke Java code from JavaScript along with parameters
How to use Servlets and Ajax?
If you're pre-populating the form fields based on parameters in the HTTP request, then why not simply do this on the server side in your JSP... rather than on the client side with JavaScript? In the JSP it would look vaguely like this:
<input type="text" name="myFormField1" value="<%= request.getParameter("value1"); %>"/>
On the client side, JavaScript doesn't really have the concept of a "request object". You pretty much have to parse the query string yourself manually to get at the CGI parameters. I suspect that isn't what you're actually wanting to do.
Passing JSON from JSP to Javascript.
I came here looking for this, #BalusC's answer helped to an extent but didn't solve the problem to the core. After digging deep into <script> tag, I came across this solution.
<script id="jsonData" type="application/json">${jsonFromJava}</script>
and in the JS:
var fetchedJson = JSON.parse(document.getElementById('jsonData').textContent);
In JSP file:
<head>
...
<%# page import="com.common.Constants" %>
...
</head>
<script type="text/javascript">
var constant = "<%=Constants.CONSTANT%>"
</script>
This constant variable will be then available to .js files that are declared after the above code.
Constants.java is a java file containing a static constant named CONSTANT.
The scenario that I had was, I needed one constant from a property file, so instead of constructing a property file for javascript, I did this.
In JSP page :
<c:set var="list_size" value="${list1.size() }"></c:set>
Access this value in Javascipt page using :
var list_size = parseInt($('#list_size').val());
I added javascript page in my project externally.

HTML5 data-attributes : How to modify array of data attached to DOM element?

I try to modify some HTML5 data-attribute with jquery.
I know how to do when it is simple like this :
<div id="element" data-options="HelloWorld"></div>
//Modify with jQuery :
$("#element").data("options","Bye Bye");
But in my case, i would like to modify a more complexe data-options (it's a joomla module).
data-options is organized like this with an array of datas :
data-options="{"title":"Test","lat":"48.6069129","lng":"7.7612831","icon":"red","popup":1},{"title":"Test","lat":"48.6069129","lng":"7.7612831","icon":"blue","popup":2}"
How can i select and modify only icon for example ?
You can use the function overload of jQuery.fn.data
$('#element').data('options', function(data){
var obj = JSON.parse(data);
obj.forEach(function(o){
o.icon = "some other color";
});
return JSON.stringify(obj);
});
The above works assuming you have the following as your data.
'[{"title":"Test","lat":"48.6069129","lng":"7.7612831","icon":"red","popup":1},{"title":"Test","lat":"48.6069129","lng":"7.7612831","icon":"blue","popup":2}]'
To properly declare the json, you can put 'em in '' instead of "" which will save you from the headache of escaping double quotes.
From comment: You will simply need to convert it from a string to an object using JSON parsing. The double-quotes are going to cause you grief though.
var values = $.parseJSON($('#element').data('options'));
One only way to include a JSON literal in a standard HTML attribute is by encoding the "'s to "s which is pretty horrible:
e.g.
data-options=";{"title":"Test","lat":"48.6069129","lng":"7.7612831","icon":"red","popup":1},{"title":"Test","lat":"48.6069129","lng":"7.7612831","icon":"blue","popup":2}";
or you can use single quotes for the delimiting (while not standard this will work on most browsers):
data-options='{"title":"Test","lat":"48.6069129","lng":"7.7612831","icon":"red","popup":1},{"title":"Test","lat":"48.6069129","lng":"7.7612831","icon":"blue","popup":2}'

JSON from Newtonsoft to JavaScript

So, I have a some json data which I create in my controller like so:
Notes = JsonConvert.SerializeObject(contact.Notes.OrderBy(x => x.DateLogged).Select(x => new
{
id = x.Id,
date = x.DateLogged,
content = x.Content,
logged = x.Username
}))
This then gets passed to the view, now which statment can I do to achieve the results of having a variable contain that json data:
var data = '#Html.Raw(Model.Notes)'
or
var data = JSON.parse('#Html.Raw(Model.Notes)');
EDIT
the content variable holds some "\n" which when passed to the view using the first choice from above generates an error, saying
Unexpected Token
it only does it with \n so what is going wrong here? the bottom method doesn't quite work.
var data = JSON.parse('#Html.Raw(Model.Notes)');
This doesn't work - you can't put a JSON literal inside a JavaScript string. Any backslash in it will be an escape character to the JavaScript parser, not the JSON parser. A newline comes out like:
var data = JSON.parse('{"content": "abc\ndef"}');
which means the string you are asking JSON to parse is:
{"content": "abc
def"}
which is not valid as you can't have a literal newline in a JSON string.
To do this with JSON.parse you would have to JS-string-literal encode the JSON output, so you would end up with "abc\\ndef". The alternative would be to include the JSON directly in the script block as var data = #Html.Raw(Model.Notes);, but there are problems with this to do with the differences between JS and JSON (primarily characters U+2028 and U+2029) and the enclosing HTML context (ie what the sequence </script does).
Getting the escaping right here is harder than it looks, so you should avoid injecting anything into a <script> block. Better to put in-page JSON data in a data- attribute and read it from the DOM; this way you can use the normal HTML escaping Razor gives you by default.
<div id="notes" data-notes="#Model.Notes">
...
var data = JSON.parse(document.getElementById('notes').getAttribute('data-notes'));
bobince is obviously correct in what he says, it makes so much sense, thanks for that.
However, my solution was to simply do:
var data = #Html.Raw(Model.Notes);
Because, Newtonsoft already has converted it to a proper JSON format, so all it needs to do, is be assigned to a variable to be manipulated.
I think grabbing the content from a the HTML DOM is a bit too much for this.

Extracting values with Javascript

I have a variable called "result",
var result;
that result value is equal to following value, please presume that is just a string :)
---------result value -----------
for (;;);{
"send":1,
"payload":{
"config":{
"website":"",
"title":"welcome to site",
"website-module":1313508674538,
"manufatureid":"id.249530475080015",
"tableid":"id.272772962740259",
"adminid":100002741928612,
"offline":null,
"adminemail":"admin#website.com",
"adminame":"George",
"tags":"web:design:template",
"source":"source:design:web",
"sitelog":[],
"errorlog":0,
"RespondActionlog":0,
"map":null
},
"imgupload":""
},
"criticalerror":[0],
"report":true
}
---------result value------------
From that value, I would like to extract tableid which is "id.272772962740259" with classic Javascript.
How can I extract the code, please let me know how can i do with simple javascript, please don't use Jquery, all I just need is simple javascript.
You can simply evaluate the value of the variable to obtain the values. However, please note that your current value is not valid JSON; that for(;;); at the beginning of the value invalidates the format. Remove that, and you can do this:
var object = eval('(' + resultMinusThatForLoop + ')');
alert(object.payload.config.tableid);
If that data is a string the parse it with a JSON parse. The following should get the value you want
JSON.parse(result).payload.config.tableid; // "id.272772962740259"
Edit: though, as Tejs says, the for(;;) invalidates the string and stops it from being parsed. If you can remove that, do.
You need to remove the empty for loop, then parse the string. DO NOT use eval; most modern browsers provide built-in JSON-parsing facilities, but you can use json2.js if yours does not. Assuming that you assign the results of parsing the JSON to result, you should be able to get that value using result.payload.config.tableid.
You should probably read a good JS reference. JavaScript: The Good Parts or Eloquent JavaScript would be a good choice.
If result is a javascript object and not a string, you can just use 'result.payload.config.tableid'.
If it is not, how do you get the AJAX result? Are you using XmlHttpRequest directly? Most libraries will give you a javascript object, you might be missing a flag or not sending the response back with the right content type.
If it is a string and you want to parse it manually, you should use a JSON parser. Newer browsers have one built in as window.JSON, but there is open source code for parsing it as well.
var obj = JSON.parse(result);
alert('tableid is ' + obj.payload.config.tableid);

How I access a variable from JavaScript and Grails?

I have a Grails variable which is of type JASONList that is rendered in a template.
Is there a way to access this list from inside a JavaScript function?
Let's say I want onresize to fit all the objects on the screen. Without making a database call and refetching the entire list from Ajax...
Let's say the template does something like this:
<g:each var="report" in="${reportList?.myArrayList}">
<li style="display:inline; list-style:none;">
<img src=" ${report?.img}">
</li>
</g:each>
<script type="text/javascript">
function resize(list) {
if (list.size <givenSize) // Pseudocode
list.subList() // Pseudocode
}
window.onresize = resize("${reportList}")
</script>
The problem with this is that for some reason Grails gsp does not render "${reportList}" as a list. Instead it renders it as the string "${reportList}".
I am probably thinking of this problem completely wrong, but is there a way to resize these objects or get them through document.getElementById or something of that nature?
The $reportList is populated by POJO as JSON conversion...
Grails variables only exist on the server side. JavaScript runs in the browser (client side). Everything that's sent to the browser is a string, so while you can use Grails to generate a piece of JavaScript like window.onresize = resize("${reportList}"), the browser will only see the string that ${reportList} evaluates to.
That means that, if you use Grails to pass a variable to the resize() JavaScript function, the parameter (list) will only ever be a string - you won't be able to access server-side list methods like list.size or list.subList(), because the list variable is no longer a list; it's just a string.
I don't know, but maybe Grails doesn't want to evaluate expressions inside script tags. Dynamically generated scripts is not a very good practice.
But until you find the exact cause, you could try something like this:
<g:each var="report" in="${reportList?.myArrayList}">
<li style="display:inline; list-style:none;">
<img src=" ${report?.img}">
</li>
</g:each>
<%= """<script type=\"text/javascript\">
function resize(list){
if(list.size <givenSize) //posudo code
list.subList() // psudocode
}
window.onresize = resize(\"$reportList\")
</script>""" %>
I'm not sure why your ${reportList} is being rendered as ${reportList}, because when I do the following:
var t = "${taskList}";
I get the following in my HTML:
var t = "[com.wbr.highbar.Task : 1, com.wbr.highbar.Task : 4, com.wbr.highbar.Task : 2, com.wbr.highbar.Task : 5]";
That said, you're still going to have issues, because JavaScript will have no idea what to do with your reportList. If it is pure JSON, you would need to eval() it so that it gets turned into a JavaScript Object.
I figured out my problem. Basically if you are using POJO in Grails the Grails as JSON conversion is not very smart. All it does is a toString on the object instead of potentially looking at all the public accessors, etc.
It is kind of disappointing, but basically I need to create the JSON conversion in the toString method of my POJO.

Categories