How do I embed EJS code in static Javascript?

Problem

I am using Nodejs and ExpressJS .

I have an HTML page , which has a Javascript file being referred to .

<script type="text/javascript" src="../javascripts/game.js"></script>

I have not embedded all the Javascript into the HTML page itself because its too big .

Now I need my Javascript ( game.js ) to access some of the variables being passed by the controller . I want to do something like this -

var max_players = parseInt("<%= table.total_players %>");
console.log("<%= table.name %>")

I am passing the table variable while rendering the page .

 exports.index = function(req,res){

//code
res.render('mytable', {table: table });

    };

But this obviously doesnt work because the JS file is being rendered as a static file . How do I go about if I need to make these variables accessible to the Javascript ?

I read somewhere that this can be achieved by renaming Game.js to Game.ejs . But where do I put the Game.js file ( so that its rendered properly and dynamically ? )

If there are any other ways to achieve this , please also let me know .

Problem courtesy of: dontknow

Solution

Probably the simplest option would be to output the globals you need from table (or table itself) in another <script> before game.js:

<script>
   var max_players = <%- JSON.stringify(table.total_players) %>;
   console.log(<%- JSON.stringify(table.name) %>);

   /* Alternative:
     var table = <%- JSON.stringify(table) %>;
     var max_players = table.total_players;
     console.log(table.name);
   */
</script>
<script type="text/javascript" src="../javascripts/game.js"></script>

Note the use of <%- ... %> vs. <%= ... %>, which will skip HTML-encoding the output as that can cause syntax errors in.

Using JSON.stringify() here takes advantage of the syntax relation between JSON and JavaScript. The values will be written as JSON data server-side, but parsed as JavaScript literals client-side.


If you want to run game.js itself through EJS, you can move it into your ./views directory, add a route for it, and res.render() it.

Note that you'll need to set the Content-Type as the assumed value will be text/html, which could some browsers will refuse to parse.

// ~/views/game-js.ejs

var max_players = <%- JSON.stringify(table.total_players) %>;
console.log(<%- JSON.stringify(table.name) %>);

// ...
app.get('/javascripts/game.js', function (req, res) {
    // code
    res.setHeader('Content-Type', 'application/javascript');
    res.render('game-js', { table: table });
});

Another option would be to have game.js make a request for table. You can see an example of this in a previous edit of this post.

Solution courtesy of: Jonathan Lonowski

Discussion

There is currently no discussion for this recipe.

This recipe can be found in it's original form on Stack Over Flow.