0

I have a web application where I add html thats repeated a lot of times via js. This html includes some thymeleaf expressions as th:each[...] and others. When I write these right into the html everything is fine and

<div th:if="${bla.start_week == 1}"></div>

evaluates to true, but if i add the same line via js like this:

<script>
ins_bla();
</script>

and

function ins_bla() {
text_part = "<div th:if=\"${bla.start_week == 1}\"></div>"
document.getElementById("blaElem").innerHTML = text_part;

it just adds the line and thymeleaf doesnt seem to do anything. How can I load the data or make sure the line gets executed whatever you gonna call it so that i get back a value? Do I need to pass bla to the js and do the if in js?

Cœur
  • 37,241
  • 25
  • 195
  • 267

1 Answers1

2

You have to be aware about the differences between server- and client-side programming, or in this case templating. Thymeleaf template interpolation happens on the server (aka the Java/Spring boot application). When it's done, it passes the result HTML to the client (aka the browser).

Any JavaScript code you have there, is executed within the browser, which means that the Thymeleaf expressions won't work, since you're no longer doing stuff on the server.

You can solve that in several ways:

  1. You could try to do everything on the server, using Spring and Thymeleaf. That means you'll have to rewrite ins_bla() in Java.

  2. You could use a partial HTML that you bind to another controller within Spring. That means that you basically do something like this:

    function ins_bla() {
      fetch('/call/to/server')
        .then(response => response.text())
        .then(html => document.getElementById('blaElem').innerHTML = html);
    }
    
  3. Rather than sending the HTML over the line, you could also write a @RestController that only sends the value of ${bla.start_week} and do everything within JavaScript. Within your ins_bla() function you could then do something like:

    function ins_bla() {
      fetch('/call/to/server')
        .then(response => response.json())
        .then(bla => bla.startWeek === 1 ? '<div></div>' : '')
        .then(html => document.getElementById('blaElem').innerHTML = html);
    }
    
  4. If you know what ${bla.start_week} will be beforehand, you could also already send it as a JavaScript variable within your initial Thymeleaf template:

    <script type="text/javascript" th:inline="javascript">
        window.startWeek = /*[[${bla.start_week}]]*/ null;
    </script>
    

    Now you can use window.startWeek within your ins_bla() function.

Note: While I'm using the fetch API to make a call to the backend, you could also use any other library out there to make a REST call.

g00glen00b
  • 41,995
  • 13
  • 95
  • 133
  • I took the fourth approach, as it was the fastest in my eyes, thanks for helping out! – Alexander Hurtig Sep 21 '18 at 08:56
  • @AlexanderHurtig No problem. Yeah, if the `bla.start_week` is known beforehand, the 4th solution is probably the fastest. The other solutions work better for dynamic data (eg. up-to-date data that comes from a database) or complex data (entire object structures). – g00glen00b Sep 21 '18 at 09:02