javascriptjqueryhtmlplayframeworktwirl

javascript variable not defined when inline


Background:

I am using PlayFramework to create a webapp (workflow) system which uses the Twirl template engine (scala based) to create my views.

Problem:

I need to store JavaScript variables inside of my template (which renders HTML), where in a separate JS file(s), I will perform operations on later.

Any existing solutions?

This can be done according to these SO questions I found:

  1. This one creates a map where data is stored in and later retrieved.

  2. This one creates a simple example of storing a variable in an inline script tag to use later

  3. Finally, this one uses a more concrete example of storing data in data structures in the template and accessing the data structures in JS after being parsed.

The example created by an active SO contributor, Biesior, helping many developers with Play! Framework questions

To summarise what should be done:

  1. Pass in some data into template

@(myData: DataObject)

  1. Add data passed in an into a script tag with a JS name

<html>
  <body>
    <script>
      let someJSDataName = @myData
    </script>
  </body>
</html>

  1. Use in JS / Google Chrome Dev console

someJSDataName.toString

This should display some result!

But what is the problem?

Let me show you.

Rendered Html:

//...
<div class="BoxMediumBlue" style="padding: 20px;">

        <script>
                let facultyDepartments = {Science=[Computer Science, Physics], Biology=[Zooology]};
        </script>

        <br>
        <div class="container-heading">
//...

When attempting to access this data in my Google Chrome dev console:

facultyDepartments
VM1209:1 Uncaught ReferenceError: facultyDepartments is not defined
    at <anonymous>:1:1

Just an FYI, using var makes no difference

Am I doing something wrong?


Solution

  • Your definition of facultyDepartments uses syntax that the JS engine doesn't understand:

    let facultyDepartments = {Science=[Computer Science, Physics], Biology=[Zooology]};

    Objects should contain key-value pairs, where the keys and values are separated by :s, and where the keys and values, when strings, have delimiters like " or '. You should try to get the template to render JSON instead, for example:

    let facultyDepartments = {"Science":["Computer Science", "Physics"], "Biology":["Zooology"]};
    console.log(facultyDepartments.Science);

    (JSON is technically a way of formatting strings, but inserting a JSON string without delimiters so that it's parsed as an object literal works too)