简体   繁体   中英

PlayFramework HTML, variable into Javascript?

Imagine a simple Play Action defined as

def reactTest = Action {
    request => Ok(views.html.hello("JOHN"))
}

and the hello.scala.html looks like this, using a basic React.js example:

@(name: String)

....

<div id="example"></div>
<script type="text/jsx">
  React.render(
  <h1>Hello, @name!</h1>,     <---- NAME PARAMETER USED HERE
  document.getElementById('example')
);
</script>

This works fine and the result will be a 'Hello, JOHN!' page. Now, I know that the Scala code is executed on the server and the JS code on the client, but I am wondering if there would be a way to pass the @name parameter to the same javascript (jsx) code if such code was in a separate .js file, and the <div> would look like:

<div id="example"></div>
<script type="text/jsx" src="@routes.Assets.at("javascripts/hello.js"></script>

Would there be a way to pass the @name parameter to the script in hello.js ?

You can save whatever you want in a global JS variable and then access it whenever you need.

For example, suppose you want to use a user object in your script. Having this html template

@(user: User)

<html>
<body>
    <script>
        var MyUserObject = {};
        MyUserObject["name"] = "@user.name";
        MyUserObject["age"] = @user.age;
    </script>
    <!-- ... -->
    <script src="your_component.js"></script>
</body>

then in your included js you could do something like this:

(function(user) {
    alert("Hello " + user.name + ". You are " + user.age + " years old");    
})(MyUserObject);

You can then improve this using a map of the values you want to use or maybe rendering your object as JSON and parsing it on JS side:

def reactTest = Action {
    request => Ok(views.html.hello(Json.toJson(user)))
}

// and then

@(user: String)

<html>
<body>
    <script>
        var MyUserObject = JSON.parse("@user");
    </script>
    <!-- ... -->
    <script src="your_component.js"></script>
</body>

Not perfect, but better than rendering that on the JS files IMO.

The @routes... in:

<script type="text/jsx" src="@routes.Assets.at("javascripts/hello.js"></script>

can be changed to:

@routes.YourController.withModel("javascripts/hello.js", model)

Then in YourController.withModel you can preprocess hello.js (such as using a templating sbt-web plugin) with the model.

You can alternatively preprocess the JS with the model before passing into this Scala HTML template.

If CPU/memory is a major concern, this can become advanced: eg, mapping between predetermined models and preprocessed static JS files, and referencing them instead. Or use other caching/CDN techniques.

So, these are just ideas in addition to the other answers given here. Enjoy.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM