Search code examples
javascriptspring-bootthymeleaf

Thymeleaf inline javascript with quotation mark not working


I have a Spring boot application using Thymeleaf. I'm setting a model variable with a String value and want to use it as variable value in javascript.

In Java I do something like:

StringBuffer data = new StringBuffer();
data.append("[ [\"").append(name1).append("\" ], \"").append(name2).append("\"] ] ");
...
model.addAttribute("dataString", data);

My code in HTML looks like:

<script th:inline="javascript">
  /*<![CDATA[*/
  var dataSet = [[${dataString}]];
  /*]]>*/
...
</script>

The result in JavaScript should be:

var dataSet = [ ["Name1"], ["Name2"] ];

But what I'm getting is in the HTML:

var dataSet = "[ [\"Name1\"], [\"Name2\"] ]";

I tried different things in the HTML/JavaScript:

  • using only one bracket [$dataString] -> results in var dataSet = [${dataString}];;
  • using this: /*[$dataString]*/ -> results in var dataSet = /*[${dataString}]*/;;
  • or: /*[[$dataString]]*/ -> results in var dataSet = "[ [\"Name1\"], [\"Name2\"] ]";
  • removing the CDATA stuff -> nothing changed

Nothing result in the correct string in JavaScript. How can I achieve the proper String?


Solution

  • You shouldn't be passing JSON strings from your controller to your model. Instead you should be passing regular Java objects and letting Thymeleaf do the encoding for you. For example, if you want a dataset that looks like this:

    [ ["Name1"], ["Name2"] ]
    

    Then you should add it to your model like this:

    // This is an array of arrays, just like [ ["Name1"], ["Name2"] ]
    String[][] dataset = {{"Name1"}, {"Name2"}};
    model.addAttribute("dataString", dataset);
    

    Then the output of

    <script th:inline="javascript">
      /*<![CDATA[*/
      var dataSet = [[${dataString}]];
      /*]]>*/
    </script>
    

    Will result in JavaScript:

    var dataSet = [ ["Name1"], ["Name2"] ];
    

    Just like you wanted, without having to manually create the string. This of course works with all kinds of Java objects, and will even auto convert getters and setters to regular JavaScript objects.

    Of course, if you really just want to add JSON strings directly from your model, you can of course use the unescaped inline.

    var dataSet = [(${dataString})];
    

    But that is really counter to how this stuff is supposed to work.