When a GET request is made on my site, I am trying to render templates that are stored on another server. Essentially my application will make a request to this server, and the response will contain the template that I would like to use. The server's response is a dust template in the form of a string.
What is the best way to render the template?
router.get('/', function(req, res) {
var options = {
host: myHost,
path: myPath,
port: myPort};
var templateReq = http.get(options, function(response) {
var templateStr = '';
response.on('data', function(chunk) {
templateStr += chunk;
});
response.on('end', function() {
var dustParams = myDustParams;
res.render(templateStr, dustParams); //THIS DOES NOT WORK
});
});
});
I understand that render looks in the 'views' folder to search for a template.
Also, I know that you can directly send HTML to the response using 'send', but by doing this I am unable to include the dust parameters.
You can use:
res.send(templateStr);
Regarding having dust populate the params in the template, you have to compile and render it before using the res.send
I wrote an npm module to do this by extending the express framework to read a template url from the view model along with a css selector of where to inject the content of the view.
You call res.render as normal but pass template url and selector rather than layout
res.render('view-name', {
template: 'https://courseof.life/johndoherty', // external url
templateSelector: '#promo-banner' // element within layout to inject view
});
It caches the template for 30 minutes before making another call to fetch the next version.
Related
example in Express I have a route that linked to my ejs middleware.
Code 1 :
app.all("/sample", function(req,res,next){
ejs.renderFile("./sample.ejs", {req,res,next,require,module:require("module")} {}, function(e, dt){
res.send(dt.toString());
});
});
everything fine in the first code. and in sample.ejs (second code) I want to request to some text file in Internet and return to HTML (and should use HTTP module)
Code 2:
<%
var http=require("http");
var url=require("url");
var opt = url.parse("http://website.com/thisfile.txt");
/* it will return "Hello World!" btw */
var dt = ""
var hReq = http.request(opt, function(hRes){
hRes.on("data", function(chunk){
dt+=chunk.toString();
});
});
hReq.end();
%>
<h2>Here is the data is <%= dt %></h2>
and while i try to my browser. it just give me
Code 3:
<h2>Here is the data is </h2>
where I want it gave me
Code 4:
<h2>Here is the data is Hello World!</h2>
How could I get that?
I just want to use HTTP Module or Net Socket Module. and I just want to edit the Code 2. Code 1 is permanently like that.
While EJS can run full JavaScript, you generally want to leave as much as possible out of the template and put more of your logic in your main express request handler.
Since the rendering is done server side anyway, nothing will change other than making it easier to read and test.
You should consider moving the HTTP request made in your EJS template into your app.all('/sample') handler and then just inject the result into your template. In this case that would be the final string collected from the HTTP request. You'll then end up with something like this. (This is untested code).
Also, while it is not required at all, I'd suggest taking a look at something like the request, this makes HTTP requests much easier!
var request = require('request');
app.all("/sample", function(req,res,next){
// Make the HTTP request
request('http://www.website.com/file.txt', function(err, response, body) {
// Render the ejs template
ejs.renderFile("./sample.ejs", {file: body}, function(e, dt) {
// Send the compiled HTML as the response
res.send(dt.toString());
});
});
});
I am currently new to nodejs and mongodb, so please forgive me for this newbie type of question.
What I want is to pass data from my mongodb file to my js file which is running my mini-game.
What I am doing right now is using jsp tags to retrieve data from my mongodb (I am following this practice from a project that I have seen, but he is doing this on his html file which is working out well for him. for my case I was just trying my luck)
var win = <%= user.win %>;
var lose = <%= user.lose %>;
var draw = <%= user.draw %>;
How do I retrieve the data I had from my mongodb to javascript?
If you have an Node.JS with Express application, there are many ways to do it. If you're using a template engine, you could render the data as part of the HTML page in a script block (or render it directly as HTML, avoiding script). Or, you might want to use an Ajax style request and send back the data to the client.
app.get('/api/users/:id', function(req, res) {
Users.findOne({ _id : req.params.id }, function(error, user) {
if (error || !user) {
res.send({ error: error });
} else {
res.send(user);
}
});
});
Once you've got that ready, you could use jQuery's ajax function for example to call the web service.
$.ajax({
url: "api/users/" + userId,
}).done(function(user) {
// here you have a complete user object that you can use
});
The code you posted makes me think that you're using a template engine though. I would expect that there is a render method with your template HTML file:
res.render('homepage', user);
Then, in the HTML:
<script>
var win = <%= win %>;
var lose = <%= lose %>;
var draw = <%= draw %>;
</script>
As the user object is the object with current context (as it was passed as the parameter in my example above), you can just directly refer to the properties of the user object directly (just win rather than user.win).
Is it possible to pass a server-side JavaScript variable to a <script> tag in an HTML view?
In my routes file I have:
exports.index = function(req, res){
res.sendfile('views/index.html', {
data: {foo: bar}
});
};
If I was using a Jade template, I could do:
script(type='text/javascript').
var local_data =!{JSON.stringify(data)}
To access the data object. However, that doesn't work for an html file. Is there a work-around for this?
Have a route send the data using res.json() and use AJAX in the html to fetch the JSON data.
http://www.w3schools.com/ajax/
I have some data in a mongodb database and want to pass it to a backbone collection when I load the home page. One way of doing this would be to set up a node route like this:
exports.index = function(req, res){
db.users.find(function(err, docs) {
var docs_string = JSON.stringify(docs);
res.send(docs_string);
};
};
But this won't work because it won't render my jade template that pulls in the backbone code, it simply shows the JSON in plain text.
Alternatively, I could render my jade template passing in the data as a variable to jade:
exports.index = function(req, res){
db.users.find(function(err, docs) {
var docs_string = JSON.stringify(docs);
res.render('index', {
title: "Data",
docs_string: docs_string
})
});
};
Then in the jade template, have a script like this to add the users to my user collection:
script
var docs = !{docs_string};
var users = new app.Users();
_.each(docs, function(doc) {
var user = new app.User(doc);
users.add(user);
})
But this seems wrong, since I don't really want to pass the data to the jade template, I want to pass it to a backbone collection. Also, with this solution I don't know how to then include an underscore template (on the backbone side of things) into the page rendered by jade on the server side.
What is the standard way of passing data from a node server to a backbone collection?
Assuming your data is an object, you should convert it to string using JSON.stringify() and then insert in a page inside script tag, so your resulting HTML looks like this (I don't use Jade):
<script>
var data = {...}; // in template instead of {...} here should be the instruction to insert your json string
</script>
Then when the page loads, your script will be executed and the data will be available as a global variable in the browser so you can initialise backbone collection using it. This all is a good idea only to bootstrap your data on the first page load (to avoid extra request) and then use API to request data for this and other pages.
Check out Steamer, a tiny node / express module made for this exact purpose.
https://github.com/rotundasoftware/steamer
I have a "partial" template that I want to use both client-side and server-side.
Is there some method or filter or something that's very similar to include except that instead of executing the template immediately, it returns a client-compiled function which I could then assign to a JS variable and use throughout my script?
At present, I'm doing this:
exports.list = function(req, res){
res.render('file/list', {
...
fileItemTemplate: jade.compile(fs.readFileSync(path.join(req.app.get('views'),'file','file-item.jade')), {client: true})
});
};
And then in my template I have:
ul#folder-list.thumbnails
each file in files
include file-item
...
script(type='text/javascript')
var fileItemTemplate = !{fileItemTemplate};
And in this way I can render some items to HTML on page-load, and then add some more in later by rendering the partial as data comes in.
This works, but it doesn't feel very DRY because I have to read in the file, and deal with filepaths and stuff in the route, and then essentially redeclare the exact same variable client-side.
Is there a nice way of doing this?
Something like this would be ideal:
script(type='text/javascript')
var fileItemTemplate = !{compile file-item};
A possible solution could be JadeAsset. See also the discussion here.
You can hook assets into Express:
assets.on('complete', function() {
var app = express.createServer();
app.configure(function() {
app.use(assets); // that's all you need to do
});
app.listen(8000);
});
To create your Jade assets:
var assets = new AssetRack([
new rack.JadeAsset({
url: '/templates.js',
dirname: __dirname + '/templates'
})
]);