Scala code in JavaScript using Scala's '@'

I am using Playframework with Scala and Mongo. I have a scala.html file that has the following parameters

@(pageData:Map[String,Any], dairyData:Map[String,Any])

The dairyData map contains a date and the datapoints of 6 lines for that date.

I also have a JavaScript file which uses Google's line chart in the same file

<script type="text/javascript">
    google.load('visualization', '1.1', {packages: ['line']});
    //google.setOnLoadCallback(drawChart);

    function drawChart() {

        var data = new google.visualization.DataTable();

        data.addColumn('number', 'Dag');
        data.addColumn('number', 'Pijn');
        data.addColumn('number', 'Stemming');
        data.addColumn('number', 'Slaap');

        data.addRows([
            [1,  1.0, 80.8, 41.8],
            [2,  30.9, 69.5, 32.4],
            [3,  25.4,   57, 25.7],
            [4,  11.7, 18.8, 10.5],
            [5,  11.9, 17.6, 10.4],
            [6,   8.8, 13.6,  7.7],
            [7,   7.6, 12.3,  9.6],
            [8,  12.3, 29.2, 10.6],
            [9,  16.9, 42.9, 14.8]
        ]);

        var options = {
            chart: {
            },
            width: 900,
        height: 480
        };

        var chart = new google.charts.Line(document.getElementById('linechart_material'));

        chart.draw(data, options);
    }
</script>

The JavaScript linechart now displays 3 lines called Pijn, Stemming and Slaap, with data for 9 days.

And a div which now displays the linechart and the data I want to display in the chart in a paragraph.

<div style="width: 1000px; height: 500px;" id="linechart_material">
    @if(dairyData.get("0")!=None) {
        @for((dairyPool,i) <- dairyData.asInstanceOf[Map[String,Any]].toArray.zipWithIndex){
            <p>@dairyData.get(dairyPool._1).get.asInstanceOf[Map[String,Any]]</p>
        }
    }
</div>

My question is, how can I fill in the linechart drawn with JavaScript with the data I have in my Scala map? JavaScript doesn't seem to work with Scala's '@'

I want to use the JavaScript linechart since all Java/Scala linecharts look very ugly. But if you have another method of doing this I would like to hear them as well.

Answers


Option 1: Embed directly

As indicated in a comment you can convert the Scala value into a JsValue, then into a String, and together with @Html you can place it in the page and assign it to a JavaScript variable.

Controller:

Ok(views.html.demo.show(Json.toJson(users).toString()))

View:

@(users: String)

[...]

<script type="application/javascript">
  var users = @Html(users);
</script>

Option 2: Get data separately

There is another approach:

  • The page only renders the page layout (no data)
  • When the page has been loaded, a JavaScript function uses an AJAX request to pull the data separately
  • Then populate the chart using the data in the response.

This scenario requires more setup, but it gives a better separation: It differs between page layout (HTML page), JavaScript (functionality, in a separate file), and data.

Advantages:

  • An "update" button does the same: Pull the data using AJAX, and refresh the chart. It does not require a full page reload.

  • You can uses the "data only" JSON for other purposes (in other pages etc.) - it's not tight to the chart page.

  • The function which returns JSON can be tested separately

Some snippets for illustration:

In the controller: Provide a method returning the data in JSON:

implicit val userFormat = Json.format[User]

private def getUsers() = {
  List(
    User(0, "root"),
    User(1, "jim"))
}

def get = {
  Action {
    request =>
      val users = getUsers()
      Ok(Json.toJson(users))
  }
}

and in JavaScript (I am using jQuery here): Provide an update() function which does the AJAX call, and use this function in the ready() for the initial display. And that function can be bound to a button as well:

function update() {
    $.ajax({
      url: "/demo/get",
      method: "GET",
      contentType: "application/json; charset=UTF-8",

      dataType: "json",

      success: function(response, textStatus, jqXHR) {
        // Populate chart using the data in the response
      },
    });
}

$(document).ready(function() {
    $("#updateButton").click(function() {
        update();
    });

    update();
});

Need Your Help

issue loading js scripts with history.js

jquery html5 history.js

Currently trying at add ajax to a site, after much reading I discovered that history.js covers all the areas i require.

In a particular project (MVC5) I could not able to add view as well as in the existing razor view Intellsense is not working in VS 2012

asp.net-mvc visual-studio-2012 razor-2

One of my project build in MVC5 where I need to modify in view, but in this project I could not able to add view by right click option ( both from view folder as well as from particular controller)...