ExpressJS Pass variables to JavaScript - javascript

I am completely lost on this; I am using NodeJS to fetch a JSON and I need to pass the variable to my page and have JavaScript use the data.
app.get('/test', function(req, res) {
res.render('testPage', {
myVar: 'My Data'
});
That is my Express code (very simple for testing purposes); now using JADE I want to gather this data which I know to render on the page is simply
p= myVar
But I need to be able to gather this data in JavaScript (if possible within a .js file) but for now just to display the variable in an Alert box I have tried
alert(#{myVar})
And many others if anyone can help be much appreciated

Try the following:
alert('!{myVar}')
It's a good idea to JSON encode the data if is more than just a string.
alert('!{JSON.stringify(myVar)}')

As Timothy said:
<script type="text/javascript"> var myVar = #{JSON.stringify(myVar)}; </script>
This can also be done as follows in if you don't like to write HTML in Jade/Pug templates:
script
var myVar = !{JSON.stringify(myVar)};
var myVar2 = !{JSON.stringify(myVar2)};
Update: For Express 4 and Pug use script. instead of script so that it will be rendered as javascript instead of html.

Well, Javascript (and V8) has a built in function to render JSON from a object, and JSON happens to be syntactially compatible with Javascript.
So the easiest way to do what your trying to do would be:
<script type="text/javascript>var myVar = #{JSON.stringify(myVar)};</script>
And, yes, you can use HTML in a Jade template.

I know I'm a bit late to the party, but I actually wrote a module (JShare) a few months ago to solve this exact problem. Check it out: https://npmjs.org/package/jshare

You could leverage Now.js for this. It easily allows you to share variables client/server side real-time.
Check it out: http://www.nowjs.com/

Related

Unable to pass jinja2 variables into javascript snippet

How do i pass jinja2 data into javascript.
I have a Flask REST url as /logs/<test_case_name>
I am trying use .getJSON() to query the above URL and hence would want to pass the jinja2 data which has the testcasename to .getJSON function.
sample code:
<script type="text/javascript">
alert({{name}});
</script>
It doesn't work.
Any suggestions please?
Try with quotes:
alert("{{name}}");
other than encapsulating the variable in a string, an alternate is jquery for profit:
its generally a bad idea to mix template language with javascript. An alternative would be to use html as a proxy - store the name in an element like so
<meta id="my-data" data-name="{{name}}" data-other="{{other}}">
then in the javascript do
var djangoData = $('#my-data').data();
this has advantage in:
javascript no longer tied to the .html page
jquery coerces data implicitly
I know this is a kinda old topic, but since it attracts a lot of views I suppose some people are still looking for an answer.
Here's the simplest way to do it:
var name = {{name|tojson}};
It will 'parse' whatever 'name' is and display it correctly:
https://sopython.com/canon/93/render-string-in-jinja-to-javascript-variable/
This is how I did it
My html Element
<!--Proxy Tag for playlist data-->
<meta id="my_playlist_data" data-playlist="{{ playlist }}">
My script element
// use Jquery to get data from proxy Html element
var playlist_data = $('#my_playlist_data').data("playlist");
See .data() documenttation for more
I just figure I would add the solution I ended up using.
It has a few advantages over the other answers:
It is 100% valid javascript at the template level (no editor/lint errors).
Does not need any special HTML tag.
No dependencies (jquery, or otherwise).
let data = JSON.parse('{{ data | tojson }}');
you can try alert({{name|safe}});
<input type="hidden" name="token_idx" id="token_idx" value='{{token|safe }}'
let token_data = document.getElementById("token_idx").value;

How to generate a pure JavaScript file with Jade

I know that Jade is for producing HTML instead of JavaScript, but for a project I'm working, it would be great, and a huge time saver, if I could do this without adding a pipe in every line:
| (function(){
| //Some JavaScript Code
| var foo="#{bar}";
| console.log("This a JavaScript file generated with Jade");
| })()
The idea is to use the output of this template as the source of a regular JavaScript include like this:
<script type="application/javascript" src="foo.generated.js"></script>
So doing something like this:
script(type="application/javascript").
(function(){
//Some JavaScript Code
var foo="#{bar}";
console.log("This a JavaScript file generated with Jade");
})()
won't solve my issue, because I need to output pure JavaScript with no DOM container element.
Is there another way to do this without adding pipes to every line? Or I have to assume that Jade was designed to produce only HTML, give up, and find other solution without Jade?
Thanks in advance!
Produce all XML, include HTML. And jade was not designed to cast large blocks of javascript. The best thing you can do is create a method for obtaining these large blocks, and modifying variables. As it is doing in Example.
I think you should use:
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Content-Type', 'text/javascript; charset=utf-8');
res.end(`(function(){
//Some JavaScript Code
var foo="${bar}";
console.log("This a JavaScript file generated with Jade");
})()`);

Transferring javascript from a view to a seperate JS file

I am working on a legacy application and I want to move some JS code onto a separate JS file.
I will have to refractor some of the code to do this. I can put #Url.Content statements into data attributes in the HTML.
But how would I replace this line of code?
var array = #Html.Raw(Json.Encode(ViewBag.JobList));
A separate JS file will not know what #Html.Raw means.
Server side code like that cannot run in a seperate javascript file. My solution for such problems is having a short javascript part in the head that runs on the onload event. There you can set variables that you can use in a seperate javascript file:
in the head:
array = #Html.Raw(Json.Encode(ViewBag.JobList));
in the seperate javascript file:
var array;
Then, in the seperate javascript file you can do with your array whatever is necessary.
The ViewBag.JobList data is only known at HTML page generation time. To include it in an external JavaScript file, you have to have another ASP.NET resource that recalculated ViewBag.JobList and then served as part of a dynamic JavaScript file. This is pretty inefficient.
Instead, do what you're doing with the URLs: pass the data through the DOM. If you're writing into normal DOM instead of a script block, you don't need the raw-output any more (*), normal HTML escaping is fine:
<script
id="do_stuff_script" src="do_stuff.js"
data-array="#Json.Encode(ViewBag.JobList)"
></script>
...
var array = $('#do_stuff_script').data('array');
// jQuery hack - equivalent to JSON.parse($('#do_stuff_script').attr('data-array'));
(Actually, the raw-output might have been a security bug, depending on what JSON encoder you're using and whether it chooses to escape </script to \u003C/script. Writing to HTML, with well-understood HTML-encoding requirements, is a good idea as it avoids problems like this too.)
I think you need to create action with JavaScriptResult
public ActionResult Test()
{
string script = "var textboxvalue=$('#name').val();";
return JavaScript(script);
}
But, before proceeding please go through following links
Beware of ASP.NET MVC JavaScriptResult
Working example for JavaScriptResult in asp.net mvc
I would also follow MelanciaUK's suggestion :
In your javascript file, put your code inside a function :
function MyViewRefactored( array ){
... your code ...
}
In your view, leave a minimal javascript bloc :
<script>
var array = #Html.Raw(Json.Encode(ViewBag.JobList));
MyViewRefactored( array );
</script>

Accessing Express.js local variables in client side JavaScript

Curious if I'm doing this right and if not how you guys would approach this.
I have a Jade template that needs to render some data retrieved from a MongoDB database and I also need to have access to that data inside a client side JavaScript file.
I'm using Express.js and sending the data to the Jade template as follows :
var myMongoDbObject = {name : 'stephen'};
res.render('home', { locals: { data : myMongoDbObject } });
Then inside of home.jade I can do things like :
p Hello #{data.name}!
Which writes out :
Hello stephen!
Now what I want is to also have access to this data object inside a client side JS file so I can manipulate the Object on say a button click before POSTing it back to the server to update the database.
I've been able to accomplish this by saving the "data" object inside a hidden input field in the Jade template and then fetching the value of that field inside my client-side JS file.
Inside home.jade
- local_data = JSON.stringify(data) // data coming in from Express.js
input(type='hidden', value=local_data)#myLocalDataObj
Then in my client side JS file I can access local_data like so :
Inside myLocalFile.js
var localObj = JSON.parse($("#myLocalDataObj").val());
console.log(localObj.name);
However this stringify / parsing business feels messy. I know I can bind the values of my data object to DOM objects in my Jade template and then fetch those values using jQuery, but I'd like to have access to the actual Object that is coming back from Express in my client side JS.
Is my solution optimal, how would you guys accomplish this?
When rendering is done, only the rendered HTML is send to the client. Therefore no variables will be available anymore. What you could do, is instead of writing the object in the input element output the object as rendered JavaScript:
script(type='text/javascript').
var local_data =!{JSON.stringify(data)}
EDIT: Apparently Jade requires a dot after the first closing parenthesis.
I do it a little differently. In my contoller I do this:
res.render('search-directory', {
title: 'My Title',
place_urls: JSON.stringify(placeUrls),
});
And then in the javascript in my jade file I use it like this:
var placeUrls = !{place_urls};
In this example it's used for the twitter bootstrap typeahead plugin. You can then use something like this to parse it if you need to :
jQuery.parseJSON( placeUrls );
Notice also that you can leave out the locals: {} .
Using Jade templating:
If you are inserting #Amberlamps snippet of code above an included static HTML file, remember to specify !!! 5 at the top, to avoid having your styling broken,
in views/index.jade:
!!! 5
script(type='text/javascript')
var local_data =!{JSON.stringify(data)}
include ../www/index.html
This will pass in your local_data variable before the actual static HTML page loads, so that the variable is available globally from the start.
Serverside (using Jade templating engine) - server.js:
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');
app.get('/', ensureAuthenticated, function(request, response){
response.render('index', { data: {currentUser: request.user.id} });
});
app.use(express.static(__dirname + '/www'));
You don't need to pass the locals variables in render call, locals variables are globals. On your pug file call don't put keys expression e.g #{}. Just use something like:
base(href=base.url)
where base.url is app.locals.base = { url:'/' };
Have you heard of socket.io? (http://socket.io/).
An easy way to access the object from express would be to open a socket between node.js and your javascript. This way data can be easily passed to the client side and then easily manipulated using javascript. The code wouldn't have to be much, simply a socket.emit() from node.js and a socket.on() from the client. I think that'd be an effective solution!

node.js javascript var available in res.render()'s target

I'm trying to make a variable (eventually to be replaced by more complex json selected from the database) accessible to client-side javascript. I wanted to load it when the page is rendered instead of an ajax call and its not going to be rendered via a template like ejs (I want to pass the data to an extjs store for a combobox). So I have a standart response I render:
function (req, res) {
res.render('index.html', {foo: ['a','b']});
}
and a blank html page I want to access foo:
<!DOCTYPE html>
<html>
<head>
<script type=text/javascript>
console.log(foo);
</script>
</head>
<body>
</body>
</html>
any ideas? I've thought of maybe writing the whole html page via res.send() (which has a few more things than the example above) but that seems like such a workaround for something that should be obvious to do...
Assuming the same array foo in your question above, here are a couple ways you could do this.
This one uses an EJS filter to write an array literal:
<script type="text/javascript">
var foo = ['<%=: foo | join:"', '" %>'];
</script>
This one encodes it as JSON, to later be parsed by your client-side javascript:
<script type="text/javascript">
// note the "-" instead of "=" on the opening tag; it avoids escaping HTML entities
var fooJSON = '<%-JSON.stringify(foo)%>';
</script>
IIRC, ExtJS can handle JSON directly as its data. If not, then you could use its JSON parser first and then hand it a local variable. If you weren't using ExtJS, you could use this to parse on the client: https://github.com/douglascrockford/JSON-js
If you choose to encode it as JSON, it would make it also make it easier to later switch back to AJAX for retrieving your data. In some cases, that would have an advantage. The page could load and display some data, along with a busy icon over the element for which you're loading data.
This isn't to say there's anything inherently wrong with including all the data in the original request. It's just that sticking with JSON gives you the flexibility to choose later.
In EJS the following should work
<script type=text/javascript>
console.log( <%= foo %>);
</script>
I do recommend against dynamically generating JavaScript though as it breaks seperation of concerns and forces JavaScript to be on.
Edit:
Turns out the above doesn't work nicely for arrays. So simply encode your data in semantic HTML. Then enhance it with JavaScript. If the JavaScript must get data then store it somewhere more sensible like the cookie or retrieve it through ajax.

Categories

Resources