node.js - express - render multiple views - node.js

I'ld like to send two successive ejs page to the client using the following code:
app.post('/', function(req,res) {
res.render('yourDemandIsBeingProceed.ejs');
//some code which require time (open an external programm, run a script, edit a response)
res.render('hereIsYourResult.ejs');
res.end();
});
So, once once the client post his form, he receives a page asking him to wait for a few seconds and then the page containing the response is send.
any suggestion?
many thx

What you can do is have client-side code in yourDemandIsBeingProceed.ejs when the page loads that performs a get/post request to a different endpoint. When the result from that is received, hide/show different elements inside yourDemandIsBeingProceed.ejs so it looks more like hereIsYourResult.ejs

What you really should do is have the user submit information via front end AJAX and put up a loading graphic until the JSON response gets back. AJAX was developed for situations exactly like this.

Related

running function after res.send

I'm trying to run this code
module.exports = async (req, res, next) => {
res.set('Content-Type', 'text/javascript');
const response = {};
res.status(200).render('/default.js', { response });
await fn(response);
};
fn is a function that calls an api to a service that will output to the client something. but its dependent on the default.js file to be loaded first. How can do something like
res.render('/default.js', { response }).then(async() => {
await fn(response);
};
tried it, but doesn't seem to like the then()
also, fn doesn't return data to the client, it calls an api service that is connected with the web sockets opened by the code from default.js that is rendered.
do i have to make an ajax request for the fn call and not call it internally?
any ideas?
Once you call res.render(), you can send no more data to the client, the http response has been sent and the http connection is done - you can't send any more to it. So, it does you no good to try to add something more to the response after you call res.render().
It sounds like you're trying to put some data INTO the script that you send to the browser. Your choices for that are to either:
Get the data you need to with let data = await fn() before you call res.render() and then pass that to res.render() so your template engine can put that data into the script file that you send the server (before you send it).
You will need to change the script file template to be able to do this so it has appropriate directives to insert data into the script file and you will have to be very careful to format the data as Javascript data structures.
Have a script in the page make an ajax call to get the desired data and then do your task in client-side Javascript after the page is already up and running.
It looks like it might be helpful for you to understand the exact sequence of things between browser and server.
Browser is displaying some web page.
User clicks on a link to a new web page.
Browser requests new web page from the server for a particular URL.
Server delivers HTML page for that URL.
Browser parses that HTML page and discovers some other resources required to render the page (script files, CSS files, images, fonts, etc...)
Browser requests each of those other resources from the server
Server gets a request for each separate resource and returns each one of them to the browser.
Browser incorporates those resources into the HTML page it previously downloaded and parsed.
Any client side scripts it retrieved for that page are then run.
So, the code you show appears to be a route for one of script files (in step 5 above). This is where it fits into the overall scheme of loading a page. Once you've returned the script file to the client with res.render(), it has been sent and that request is done. The browser isn't connected to your server anymore for that resource so you can't send anything else on that same request.

how to render a file and send data to page in the same GET request

I am using angularjs on client-side and experss.js in server-side , i want to render a page and send data to the page (to fill a table) in the same get request
i tried using ejs engine to fill the table in the server-side and then render the page , but the problem with this solution is that the client-side (angularjs) cant access or manipulate the data.
other solution is (atrivial one) is to
make get request to get the page on cient-side
render the page on server-side
make another get request from client-side to get the data
send the data from server to client
The problem with this is that it contains two get requests.
Is there a possible way to render the page and send the data in one get request?
I am doing this to make the loading on site more efficient. Can i acheive more efficiency with one GET request ?
No, you can't. You can only have a single response to a given request. The browser is either expecting an HTML document or it is expecting JSON, it doesn't make sense to give it both at once. but you could render the page and send the data at the same time:
res.render('reports',{data:json});
and then access those data in the newly rendered page.
alternatively you could send a flag when making the call , and then decide whether you want to render or send based on this flag.
Or Ideally, it needs to be 2 separate route, one spitting json and other rendering a view. Else, you could pass a url param, depending on which you return json or render a view.
router.get('/reports/json', function(req,res){
var data = JSON_OBJECT;
res.send(data);
});
router.get('/reports', function(req,res){
var data = JSON_OBJECT;
res.render('path-to-view-file', data);
});
To access data in an AngularJS app without a second server request, include a .value script:
<script>
angular.module("myApp").value("myData",
<JSON data here>
}
</script>
Then in the controller, inject it:
app.controller("myCtrl", function($scope, myData) {
$scope.data = myData;
})
For more information, see
AngularJS angular.module API Reference - .value method
Could you please try using rout.getparam and pass values in route in the get request

Why is res.render() not doing changing the front-end? [duplicate]

I have basic express js application with following route:
router.get('/', function(req, res){
res.render('login');
});
It works fine - after logging into main page on my localhost, html from login.pug is nicely rendered on client side. However when my app runs, sometimes I want to render another pug file, when there already is html rendered on client side:
app.get('/dashboard', function(req, res){
res.render('dashboard', {user: req.query.login});
});
But when get request is send on'dashboard'path, nothing happens. As I understand, this happens because res.render just parses pug file into HTML and sends it to client as plain string (which I can inspect in browser developers tool, when I check AJAX response I see exactly rendered HTML).
Now my question is: is there a way to render HTML from res.render in client automatically? So on server side I just write res.render('template') and on client side page is re-rendered without handling the response?
I know I can clear whole DOM and append received string into document.body, I know also that I can make a POST form request and then page will be re-rendered automatically, but I want to avoid both solutions (don't ask why).
Thank you for help in advance.
When your Javascript sends an Ajax request, the response from that Ajax request is just returned back to your Javascript. That's it. The browser does not show anything. If you want to do something with that response, then it is the responsibility of your Javascript to do something with it (insert it in the page to show it, etc...).
If what you really want is that you want the browser to actually go to the /dashboard URL and then show that page, then your Javascript can just do:
window.location = '/dashboard';
This will tell the browser to fetch the contents of that URL, it will make a request to your server, your server will return the rendered HTML and the browser will display it in the page and show /dashboard as the URL in the browser bar. That should do everything you want.
So, it's totally up to your Javascript. Pick the right tool for the job. Either fetch data for your Javascript with an Ajax call and process the result in your Javascript or instruct the browser to load a new page. One or the other.
But when get request is send on'dashboard'path, nothing happens. As I understand, this happens because res.render just parses pug file into HTML and sends it to client as plain string (which I can inspect in browser developers tool, when I check AJAX response I see exactly rendered HTML).
Yes, that what Ajax requests do. They fetch content from the server and return the data back to your Javascript (and only to your Javascript).
is there a way to render HTML from res.render in client automatically?
Yes, use window.location = '/dashboard'; from your Javascript.
So on server side I just write res.render('template') and on client side page is re-rendered without handling the response?
Not from an ajax call. Ajax calls never automatically display content. Never. Ajax calls are programmatic requests that return data to your script. That's what they are. But, yes from Javascript you can cause content to be automatically displayed by setting window.location to a new URL.

Send flash messages like notifications without reloading page

I am trying to implement flash messages on a page in such a way, that they act like status updates to something a user has submitted on that page. In detail, there is a form on that page and once the user pressed submit, it is posted to a route which handles processing, which however takes some time.
During that processing, I would like to give status updates on the very same page, ideally without reloading the page all the time.
As an extreme example, how could something like this work:
app.get('/index', function(req,res) {
for (var i = 0; i < 100; i++) {
//send a flash every 2 seconds
setTimeout(function(i) {
req.flash('This is ' + i);
}, 2 * 1000 * i, i);
};
res.render('../views/index.ejs');
})
Is this possible? I had a look at 'express-flash-notification', for which I am unsure though if it can do this.
Generally flash notifications add a bit of extra information when you're templating a new page. Libraries such as express-flash-notification won't be much use if you'd rather not reload the page.
The common approach for this scenario is to make a HTTP call in the browser using JavaScript and dynamically update the DOM with with the returned information. You might choose to use something like AJAX (found in jQuery) for this.
The general flow would be this, but you'd tailor it for your specific needs.
Send up the form using an AJAX call from frontend JS, (perhaps you're processing an image or something).
The server sends back a 200 OK response to indicate the upload was successful.
The frontend then makes a HTTP request every few seconds to the server to ask for a status update. This is returned as json (res.json({})). The frontend JS then displays this as needed.
You may choose to use something like web sockets for this status update as well, but if this is your first time approaching frontend AJAX calls then I'd suggest polling (making a request once every few seconds) for now.

how to send just a 200 response in express.js

I have node.js 5.2.0, express 4.2.0 and formidable 1.0.17.
I created a simple form to save a textfield and a photo. It works fine, but the problem is, after the data are uploaded, I can see in the console that the POST is not finished, its still Pending.
In order to finish it I added this to my code
form.on('end', function() {
res.writeHead(200, {'Content-Type': 'text/plain'});
});
I just want to send the headers and nothing on the page. I want the system to get a 200 ok response without having to print anything on the page. But the POST is still pending.
How do I fix this, without having to print anything? What kind of headers I have to send?
Thanks
UPDATE
If I do
form.on('end', function() {
res.end();
});
The POST finishes normally, but I get a blank page. Why is that? I just want to upload some stuff, not print anything on the page, not redirect, stay in the same page.
Thanks again
Try this instead:
res.sendStatus(200);
Or if you want to continue using explicitly defined headers, I believe res.end() needs to be called at some point. You can see how res.end() is utilized in the Formidable example.
The blank page is most likely the result of your client-side form handling. You may want to override the form's submit method and manually post to your express service to prevent the automated redirection you are seeing. Here are some other stackoverflow responses to a question involving form redirection. The answers are jQuery specific, but the basic idea will remain the same.

Resources