Accessing Express.js local variables in client side JavaScript - 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!

Related

Trying to pass a string variable to a javascript scope inside html using handlebars-express

I am willing to pass a variable from server-side to client-side using handlebars-express, unfortunately to no avail.
Upon browsing the content here for quite some time, I may need assistance to sort it out.
Checked whether the object passed is of string type: Yes.
Tried couple of combinations of retrieving the data without success.
getDeviceID method below works as expected - checked to confirm that it returned the desired string.
authMe.js (router):
if (userInSystem) {
var userDeviceID = await helpers.getDeviceID(usersSheetID, scope, Username);
res.render("signinSuccessful", { dID: userDeviceID });
}
signinSuccessful.html:
<body>
<script>
var dID = '{{dID}}'; ///// ->
console.log(dID); //////// -> need elp with these two lines
</script>
<div class="container-login100"></div>
<script>signinSuccess()</script>
</body>
In app.js I have the following requirements:
var exphbs = require('express-handlebars');
app.engine('handlebars', exphbs());
app.set('view engine', 'handlebars');
It always prints '{{dID}}' even though I was under the impression this is the method of handling the string variable sent.
Thanks in advance!
I suffered a problem like this too where I had to pass in the values from a database into a client side script in my handlebars file and this didnt work. What I did was to save the value which I wanted in the client side script in the data-* attributes of some div which you can hide also if you want to like this
<div style="display:none;" data-value="{{dID}}" id="value"></div>
Than you can retrieve that value from the script using javascript or jquery
Using Javascript:
var dID = document.querySelector('#value').getAttribute('data-value');
Using JQuery:
var dID = $('#value').attr('data-value');
You can learn more about data-* attributes from this link
https://www.w3schools.com/tags/att_global_data.asp

Getting value from a console.log to html

The function I have written works fine and the value correctly writes to my terminal onSubmit, however I'm struggling to piece together why this code isn't updating my html.
router.post('/index', function(req, res, next) {
// ...Get form values, do calculations to get toCost value.
console.log('$' + toCost);
$(document).ready(function() {
var output = document.getElementById('cost');
output.innerHTML = toCost;
});
res.location('/');
res.redirect('/');
})
I receive the following error and jquery is loading fine.
$ is not defined
Admittedly this is an over-engineered node/express app. The code snippet lives wrapped in a route file, inside a post request.
How do I get my value onto the html?
Jade layout
extends layout
block content
form(...)
div#cost
The normal way to do this would be as follows:
router.post('/index', function(req, res) { <<< 'next' removed (only needed if using middleware)
// ...Get form values, do calculations to get toCost value.
console.log('$' + toCost);
res.render('indexTemplate', {cost: toCost}); <<< pass toCost through to jade as 'cost'
});
Then in your jade file for the indexTemplate you can reference the 'cost' variable passed in like this:
indexTemplate.jade:
extends layout
block content
form(...)
div#cost #{cost} <<< adds the cost variable to page
Then the value of toCost will appear in the resulting page.
No jQuery is required on the server side.
jQuery is made for DOM manipulations and there's no DOM on a server.
Try using 'jsdom'.
jQuery is made for client side scripting, not for server-side client manipulations.
It seems that you're trying to make changes on client-side from your backend. It doesn't work that way.
You could create a variable on backend for storing calculation result. And get this value by get query from client-side
You're tring to reach DOM (that is on client side) from NodeJS on a server side. It doesn't work that way.

How do I pass node.js server variables into my angular/html view?

I have this route in my app.js file that starts the server
app.get('/view/:item_id', function(req,res){
var A = 5;
res.render('view_item');
and I have this in my view_item.html:
<p>{{A}}</p>
I want it to display the variable value - 5. If I were using a template engine such as jade it would be easy. I could change that third line of my server code to res.render({A:A},'view_item');
But I am using html as my template engine. My research so far has told me that using a template engine with angular is usually a bad idea, and there is always a way to do it using angular's built in template system. So how do I do this? Do I somehow pass it to the $scope and include like
<script>
$scope.A = {{A}};
</script>
I haven't seen this done anywhere so I don't think its the way to go.
This is a two step process.
First, you need to use a library(server library) like express in node to set the proper routings (REST Services) to respond to your Requests:
Server Side
//app = express();
app.get('/api/:paramID1/:paramID2',function(req, res){
return res.json({ A: 5 });
});
On the client side, you need an ajax call to invoke the service like:
$http.get( "/api/1/abc").success(function( data ) {
$scope.A= data; //from your sample;
alert( "Load was performed. " + data );
});
Please note that when using REST there are different type of "methods" that can be invoked depending on your needs, such as POST, DELETE, UPDATE or the one just mentioned in the example GET.
If you are using Angular you should probably be building a single page app -- this would apply for most of the modern front end frameworks. For SPAs you start out with a basic html file (probably index.html). Then, your framework handles the rendering of everything else. Your server may also emit templates, but it will never render anything itself.
app.get('/view/:item_id', function(req,res){
This shouldn't be rendering anything or returning HTML. Instead, you should be returning data that the front end will use to render -- preferably as JSON.
res.json({A: 5});
Then with Angular you would do something like
$http.get("/view/1").success(function (data) {
ctrl.A = data.A;
});
Your html/template would have something like
<div ng-controller="ctrl as ctrl">
<div>{{ctrl.A}}</div>
Once $http.get completes, ctrl.A is populated.

How to access data from res.render in Express

I want to access the data that was sent from response.render in my html file.
I have this code in my server.
app.post('/game',function(req,res){
var name = "Jude";
res.render(__dirname +'/game.html',{user:name});
});
How do i access user variable in my game.html?
You'd have to use a template language like Jade, EJS and so on. If you already have the HTML in place, try EJS.

ExpressJS Pass variables to 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/

Categories

Resources