6

I'm trying to use a Spring variable in javascript:

Map<String, List<String>> states;

and I found some information here

so I tried:

<script th:inline="javascript">
  /*<![CDATA[*/ 
    var xxx = ${states};
    console.log(xxx);
  /*]]>*/
</script>

In my browser's source tab I have something like:

var xxx = {STATE1=[a, b, c, d]};
console.log(xxx);

and the error is: Uncaught SyntaxError: Invalid shorthand property initializer.

I also tried with: var xxx = /*[[${states}]]*/ 'foo'; and if i print console.log(xxx), I got 'foo'.

8
  • did you tried wrapping the xxx variable value with quotes to make it a string? just to check! Commented Aug 29, 2017 at 8:10
  • It is working with '' but the problem is that in this way I don't have object (hashmap) but String so I can't do something like xxx['STATE1'] Commented Aug 29, 2017 at 8:22
  • It looks like your map is serialized in a strange way. According to doc thymeleaf should write Maps correctly. Do you have the Jackson library in your classpath? Commented Aug 29, 2017 at 8:30
  • I do have it. I'm passing the hashmap in this way: Map<String, List<String>> states... model.addAttribute("states", states); @JakubCh. Commented Aug 29, 2017 at 8:40
  • @ImeshChandrasiri Sorry, I forgot to tag you in my comment. Commented Aug 29, 2017 at 8:51

2 Answers 2

3

This error is due to {STATE1=[a, b, c, d]} is invalid Javascript object.

The explanation is very trivial: you're seeing the product of server side rendering (you're using Thymeleaf as fat as I can suggest by th:inline tag). So on the server your map object get's rendered as {STATE1=[a, b, c, d]} string. On your client (browser) you get the page with this string, nothing else. There is already no any Java object. Just string. And this string is invalid initialization of an object in Javascript.

So you simply cannot use map this way. You cannot parse this with JSON.parse because it is invalid JSON (there should be : used instead of =).

Hope this helps!

P.S. If you will try to replace = with : in Javascript it will work the other way than you expect: the array [a, b, c, d] will be treated as an array of variables with the names a, b, c and d so you will have to ecnlose it in ''. But I suggest to throw away this idea and rethink you approach. It is not the way it should be used.

Sign up to request clarification or add additional context in comments.

2 Comments

@NikNik as Java object - for sure. using server side rendering you will get string representation. you can make the dirty hack: make a wrapper object with the map field and override toString so that you could generate there valid JSON. it should work, however it is so dirty that I wouldn't touch that with a sixty-foot pole (Cartman from South Park (c)). you should write it in response body (on server) and make an AJAX call in Javascript (if you're not planning to use any frontend frameworks like AngularJS, Angular, ReactJS, VueJS and etc).
I posted how I solved my problem. Thank you for you effort :) I upvoted your answer.
1

I solved my problem using your comments:

1) There was missing single quote:

<script th:inline="javascript">
  /*<![CDATA[*/ 
    var xxx = '${states}';
    console.log(xxx);
  /*]]>*/
</script>

2) The object must be parsed so:

  var hashmap = $.parseJSON(xxx);

3) And before I need to serialize my object (this is not ajax call so I need to serialize it manually):

Map<String, List<String>> states...
  model.addAttribute("states", new ObjectMapper().writeValueAsString(states));

So now I'm able to read my object:

var myList = hashmap['STATE1'];
console.log(myList ) 

will print [a, b, c, d] and I can loop over:

for(i in myList ){
  console.log(myList[i]);
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.