Monday, June 3, 2024
 Popular · Latest · Hot · Upcoming
143
rated 0 times [  146] [ 3]  / answers: 1 / hits: 46301  / 11 Years ago, thu, january 16, 2014, 12:00:00

How simultaneously to render a page and transmit my custom data to browser. As i understood it needs to send two layers: first with template and second with JSON data. I want to handle this data by backbone.



As i understood from tutorials express and bb app interact as follows:




  1. res.render send a page to browser

  2. when document.ready trigger jQuery.get to app.get('/post')

  3. app.get('/post', post.allPosts) send data to page



This is three steps and how to do it by one?



var visitCard = {
name: 'John Smit',
phone: '+78503569987'
};

exports.index = function(req, res, next){
res.render('index');
res.send({data: visitCard});
};


And how i should catch this variable on the page- document.card?


More From » html

 Answers
31

I created my own little middleware function that adds a helper method called renderWithData to the res object.



app.use(function (req, res, next) {
res.renderWithData = function (view, model, data) {
res.render(view, model, function (err, viewString) {
data.view = viewString;
res.json(data);
});
};
next();
});


It takes in the view name, the model for the view, and the custom data you want to send to the browser. It calls res.render but passes in a callback function. This instructs express to pass the compiled view markup to the callback as a string instead of immediately piping it into the response. Once I have the view string I add it onto the data object as data.view. Then I use res.json to send the data object to the browser complete with the compiled view :)



Edit:



One caveat with the above is that the request needs to be made with javascript so it can't be a full page request. You need an initial request to pull down the main page which contains the javascript that will make the ajax request.



This is great for situations where you're trying to change the browser URL and title when the user navigates to a new page via AJAX. You can send the new page's partial view back to the browser along with some data for the page title. Then your client-side script can put the partial view where it belongs on the page, update the page title bar, and update the URL if needed as well.



If you are wanting to send a fully complete HTML document to the browser along with some initial JavaScript data then you need to compile that JavaScript code into the view itself. It's definitely possible to do that but I've never found a way that doesn't involve some string magic.



For example:



// controller.js
var someData = { message: 'hi' };
res.render('someView', { data: JSON.stringify(someData) });

// someView.jade
script.
var someData = !{data};


Note: !{data} is used instead of #{data} because jade escapes HTML by default which would turn all the quotation marks into " placeholders.



It looks REALLY strange at first but it works. Basically you're taking a JS object on the server, turning it into a string, rendering that string into the compiled view and then sending it to the browser. When the document finally reaches the browser it should look like this:



// someSite.com/someView
<script type=text/javascript>
var someData = { message: hi };
</script>


Hopefully that makes sense. If I was to re-create my original helper method to ease the pain of this second scenario then it would look something like this:



app.use(function (req, res, next) {
res.renderWithData = function (view, model, data) {
model.data = JSON.stringify(data);
res.render(view, model);
};
next();
});


All this one does is take your custom data object, stringifies it for you, adds it to the model for the view, then renders the view as normal. Now you can call res.renderWithData('someView', {}, { message: 'hi' });; you just have to make sure somewhere in your view you grab that data string and render it into a variable assignment statement.



html
head
title Some Page
script.
var data = !{data};


Not gonna lie, this whole thing feels kind of gross but if it saves you an extra trip to the server and that's what you're after then that's how you'll need to do it. Maybe someone can think of something a little more clever but I just don't see how else you'll get data to already be present in a full HTML document that is being rendered for the first time.



Edit2:



Here is a working example: https://c9.io/chevex/test



You need to have a (free) Cloud9 account in order to run the project. Sign in, open app.js, and click the green run button at the top.




[#73118] Wednesday, January 15, 2014, 11 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
makaylahh

Total Points: 128
Total Questions: 106
Total Answers: 97

Location: Tanzania
Member since Wed, Feb 24, 2021
3 Years ago
;