Boostrapping data with Static html page with Expressjs - javascript

I am currently using static pages (will move over to Jade soon) and I want to pass some information into my index.html when the first request is made.
I know this is possible with jade and I wanted to know what my options are if I use a static page?
For example, I need something like this:
app.get('/', function(req, res) {
res.render(config.rootPath + '/public/index.html', {data: 'usernamehere'});
});
and in my index.html I have a script tag:
<script>
var currentUser = data; <-- I know this will never work...
</script>
So should I make a call from my script tag to get the information or is there another way?

Did you consider express-expose?
"Expose helpers and local variables to the client-side." See the repo.

Related

EJS not rendering ejs code on client side

I tried rendering EJS code that I sent from home.js to home.ejs as a string but it didn't work. I'm trying this now but nothing seems to work. My code is:
home.js
var templates = {};
templates.onScroll = fs.readFileSync('views/partials/onScrollAppendPost.ejs', 'utf-8');
res.render("users/home", {templates: templates});`
home.ejs
var template = new EJS({text: <%- JSON.stringify(templates.onScroll) %>}).update('#mainContainer', {postArr: postArr});
Edit:
What im trying to do is I want to detect when a user gets to the bottom of the page. With this code:
$(window).scroll(function () {
if ($(window).scrollTop() == $(document).height() - $(window).height()) {
//get post data and append post
}});
When the user gets to the bottom of the page i want to append ejs code to the page. Basically i want to communicate between ejs and js.
Based on the example at http://ejs.co, you first need to include a browser build of ejs in your page:
<script src="ejs.js"></script>
Then you can use EJS client-side like this:
var html = ejs.render('your template here', {postArr: postArr});
$('#mainContainer').html(html);
Here's I'm assuming postArr is set appropriately, possibly as the result of an AJAX request.
As you're using EJS to generate EJS it all gets a lot more difficult to understand but the relevant code in your home.ejs would be something like this:
var html = ejs.render(<%- JSON.stringify(templates.onScroll) %>, {postArr: postArr});
$('#mainContainer').html(html);
This assumes that the onScroll template doesn't include any other templates. You haven't specified whether home.ejs is being used to generate HTML or JavaScript so it's unclear precisely what other escaping considerations might apply but it's possible that won't be a problem.

Nodejs, Express How to pass variable to route and use it in external JavaScript file?

I am working on a web app using MongoDB Express NodeJS stack and in one of the routes I am getting array from database and then passing it to route.
Code:
app.get("/badges/new", function(req, res) {
Colour.find({}, function(err, foundCoulours) {
if(err){
console.log("error: "+ err);
res.redirect("back");
} else {
res.render("badges/new",{foundCoulours:foundCoulours})
}
});
});
All done easily but here is a bit that I am stuck at the moment: I want to use jQuery to add elements onto the page depending on the result that came from server. I can do it using script tag and in-line JS on the ejs file without any problems but what I would like to do is to use external JavaScript file so my ejs wouldn't look as massive just with <script src="public/foo.js"></script>.
Question: Is there a way to pass foundCoulours to "public/foo.js" file after it was passed to route? Or maybe I can pass it straight to "public/foo.js" file from the request route.
You can sequentially load the scripts. As below:
Jade
body
script(type='text/javascript').
var foundCoulours= #{foundCoulours}
script(type='text/javascript', src="foo.js")
EJS
<script>
var foundCoulours = <%= foundCoulours>
</script>
<script src="public/foo.js"></script>
Explained:
As we are loading foundCoulours variable in global scope, it is directly accessible in foo.js, as it is loaded after the variable is initialized.

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 can I forward a querystring passed to nodejs to a page served via res.render?

Within my nodejs file I am rendering a page called foo.html. Inside of foo.html, I am using ajax to pull variables from a querystring and load an appropriate xml doc accordingly.
The problem is, if I run my nodejs server, we'll call it localhost, and I append the querystring to that, then the server will consume the querystring rather than the ajax call inside of foo.html.
Is there a way to forward the querystring directly to foo.html?
From inside the nodejs file, server.js:
app.get('/', function (req, res) {
var query = req.query;
if (query) {
if (query.screen == "page1") {
res.render('foo.html');
}
}
});
i can think of 2 ways of doing this
1st way -) you can change your rendering engine and pass the query string variables as local variables to the template and store those values as variables inside a <script></script> tag
2nd way -) keep the html but don't render the file load it and modify it to contain the same script tag with the variables,
in both cases once your page is loaded your JS will be able to access the variables
-------------HTML FILE----------------
<script>
var a=/*text-to-replace-for-A*/;
var b=/*text-to-replace-for-B*/;
</script>
--------------REQUEST HANDLER-----------
var fs=require('fs'); //this goes in the require section
//this goes inside your function
fs.readFile('/etc/passwd', function (err, data) {
if (err) throw err;
var finalHTML=data.replace(/\/\*text-to-replace-for-A\*\//g,variableA).replace(/\/\*text-to-replace-for-B\*\//g,variableB);
res.send(finalHTML)
});
something like that should notice i am using a simple readfile and send which is not the fastest solution but is the simplest one using html modification. you can also use streams to modify the files in memory on the fly. you can find the readfile function reference at: http://nodejs.org/api/fs.html#fs_fs_readfile_filename_options_callback

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!

Categories

Resources