MLister
MLister

Reputation: 10300

Is it possible to run javascript code based on template variables in Tornado?

If a handler returns a variable along with a template:

self.render('page.html', enabled=enabled)

where enabled is a boolean variable.

So far I know I can do things like:

{% if enabled %}
    ...
{% end %}

within the HTML part of the template.

But can we conditionally run some javascript code based on this enabled variable in the Tornado template? In other words, can we access the value of this variable in javascript embedded in the template?

Upvotes: 4

Views: 2256

Answers (1)

jsbueno
jsbueno

Reputation: 110271

Of course - Whatever is in the template between the {% if ... %} and the { % end %} directives will only be sent to the browser in case the if the expression is True. So, anything in there, be it a <script > tag with inline javascript, or a <link> tag importing a javascript file from somewhere will only be transmited over the network in that case.

You could even place a template if or fordirective inside Javascript code itself, to enable or disable parts of code based on conditions known to the server code. This, unlinke embedding or not a whole piece of code, I think would not be considered a good pratice - because it would entangle the server and client sides of your code in undesirable ways.

To access the variable from javascript, just do:

var enabled = {{ enabled }};

The value inside the {{...}} marker is rendered with the server variable.

In this case, to ensure the value in enabled to be compatible across Python and Javascript, you should use the number 0 for False and 1 for True (because if you use Python booleans, the template will render as var enabled = True; - which is not what javascript would expect, as the reserved "true" in Javascript is lowercase)

The only restriction is that you can only set teh server-side variables before the page is sent to the browser. So, if you need to set any any variable on the server side that depends on user's action on the page displayed, this way of doing things won't cut it anymore (only with a page reload). the way to make a page to be interactvely updated without reloading is to rely on asynchronous comunications from javascript (formerly known exclusively as "ajax").

edit - The O.P further asked:

here is a problem: when I return a string variable such as myvar='foo-bar' to the template, and when this {{myvar}} get evaluated in JS code, JS apparently interprets foo-bar as a variable name instead of a string. In this case, it will cause error because - denotes subtraction. How do I make JS recognize foo-bar as a string value?

Again, what is going on is quite simple: the {{ <expr> }} template operator inserts the string representation of the rsulting expression - so if you have in python myvar = "bla" and on the template var myvar = {{ myvar }}, that gets rendered (and sent to the client browser this way) as var myvar = bla - without quotes around bla - that's why javascript treats it as a variable name. The workarounds for this are putting extra quotes around your variable, if it is a string, either on Python side or on the template.

On the template you can do: var myvar="{{ myvar }}" - or, on the Python side, when defining myvar: myvar = '"%s"' % "bla"

Upvotes: 5

Related Questions