Using data from GET request without user's page reloading - node.js

So, the subject is one-page web app on Node.js + express + ejs + socket.io + mongoose all the latest versions.
let's imagine user inputs in his browser's adress bar "www.app.com/data". I want to grab response from db according to this data, send it back to user and render for him basic 'www.app.com' page with implemented in it db response.
I'm curious about two options: what is the best way to do this with and without page reloading, for example if user is already on the page and I do not want to reload it - just change accordingly to db response.
I can grab this data from his get request:
app.get('/:id', function (req, res) {
console.log('got' + req.params.id);
///some db magic here... poof, response ready///
})
But then what I do next? I was thinking about sending response by sockets.io, which I am using anyway, but then how can I just end this GET without any reloading of user's page? If i must send something back, I can respond by render this page again with ejs, but then I can't rely on sokets, cos while reloading - he is disconnected from them.
Can you shed a light on my confusion?

At the end I'm using URI Fragment identifier i.e # in URI.
If user inputs http://YourAwesomeApp/#hashtag you can catch hashtag by using this listener:
window.onhashchange = function () {
var hash = location.hash.substr(location.hash.indexOf("#") + 1);
//now hash = hashtag, do your stuff.
};
It perfectly fits my needs.
Be aware, that window.onhashchange also fires if you change hash via JS (location.hash = something).

Related

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

External web service redirects the user and posts data to my callback URL. How do I render the posted data to the user in an Express/Next.js app?

Any help would be hugely appreciated! Been stuck on this for a few days.
I have an Express/Next.js app where:
I send the user to an external website
user makes a payment
external website redirects and posts data back to my callback URL.
So now I have the user on a mysite.com/payment-complete route but also want to display the data that was sent back.
I have an app.post endpoint to successfully grab the data:
app.post("/payment-complete", async (req, res) => {
const transactionID = req.body.trans_id;
});
How would I pass the data to the user who is already on that route? Or pass the data before the page is rendered?
The flow of data is third party > my server > user and I'm not sure how to make this work.
I'd be grateful for any help/direction with this.
If anyone comes across this - the problem was that in Express (and other languages) you can't redirect or render a view for an AJAX POST request but you can if the POST request is coming from a submitted html form. The web service was in fact POST-ing the data and redirecting my users with a form and so I could render a view.
Following code worked using Handlebars templating engine to send the render.
router.post("/payment-ok", async (req, res) => {
const transactionID = req.body.trans_id;
return res.render("rendertest", { id: transactionID });
});
Should also possibly work with app.render to send a Next.js view instead, but I wanted to render from a separate routes file.

MongoDB, Node, Express, EJS - Pass a array/variable from backend to frontend (from route to client)

I've been trying to figure out a better way to push a variable from the backend to the frontend. Right now I do something like this.
I have a MVC-pattern, so when hitting the route
app.get('/fil', middleWare.isLoggedIn, user.fil)
... trough node does some querying the DB, and pass on the data.
exports.fil = async (req, res) => {
try {
faktura = await Lan.find().populate('client', 'namn kundnr')
res.status(200).render('pages/createInvoice', {
faktura: faktura
});
} catch (err) {
return res.status(500).send({
message: err.message || "Some error occurred while retrieving datas."
});
};
};
... it generates the page, with the help of EJS (i love EJS) and then pass it on to the client/user.
And in the .ejs-file that is served to the client/user I add the following
<script>
var fakturor = <%- JSON.stringify(faktura) %>;
</script>
which then means that I use up the variable and work with it with JS.
And this is where my question pops up. Is this a good way to do it or is there any other way to handle it?
I guess one idea is to let the user to query the DB straight from the page, but in my case I believe it wouldn't actually be better for the user to do so (the user will reieve like 100 different rows that they will be able to filter and then download a file of)
But is there any other ways I could do this without the script-tag? Like i said, I guess a ajax-call from JS/the client could be used but could you do it any other way? Can EJS do it any other way?
ejs is used for static pages mainly, if you want to build a dynamic page I would look for a single page application framework like angular and react.
if you still want to use ejs you can use ajax call to the server to load a variable from the DB.
I would never query directly from Front end to DB because then you are not controlling the security of the server, always go through the BE.
also try to think if you really need a variable in the front end, can you solve your problem using rendering only?

Is there any way of redirecting from one route to another with data from first route to second in node.js?

What i want to know is whether is it possible to redirect from one route to another with data from first route to second one? For example from the HTML form i POST the data(say phone number) to a route (say '/route1') and with success operation at this route i want to send phone number to '/route2' from'route1'. If it is possible then how should I do that?
There are a number of ways to pass data in a redirect.
Put the data in a query parameter on the redirect URL http://www.whatever.com/somePath?ph=123-456-1234. Either the server or the client can access the data when rendering the redirected page.
Put the data in a server-side session object where it will be available when rendering the redirected page.
Use a "flash" middleware which saves some data for only the "next" request from that particular browser so the data will be available server-side when rendering the redirected page.
Of these options, the first one is clean because its stateless and the data is available to either client or server. It doesn't require any temporary server-side storage either.
What i want to know is whether is it possible to redirect from one route to another with data from first route to second one?
Once your data is posted without error, you can redirect the client that way :
// POST data
app.post('/oneRoute', function(req, res) {
let myData = new MySchema();
myData.phoneNumber = req.body.phoneNumber;
// save data to DB then redirect to /anotherRoute
myData.save(function(err) {
if (err) {
// error
} else {
// redirect path
res.redirect('/anotherRoute');
}
});
});
Then, if you want to pass the data in a query parameter on the redirect URL, you can :
(...)
} else {
// redirect path + query parameter
res.redirect('/anotherRoute?phonenumber='+req.body.phoneNumber);
}
(...)
What Next ? You can get the query string from the url of your redirected path...
http://localhost:3000/anotherRoute/?phonenumber=6876766242425
Note : as mentioned by jfriend00's reponse, this solution is clean and stateless, the data is available to either client or server.
See also res.redirect() & req.query
Session : in a different manner , if you want to store the data server-side, you can use Simple session middleware for Express package...

How can I send information from NodeJS server to client side?

For example, I want to signal to the client side that a username sent via the POST method in an HTML form already exists in my database.
I know how to recuperate POST data with body-parser and I know how to look it up in a MySQL database.
I know that I could use Ajax to write an error message directly on the form. What does my NodeJS server need to send and how does it send this information?
I've searched through numerous tutorials and I just found solutions where they send a new HTML page. I want to keep my web page the same and use functions like appendChild() to post the error message.
There are a couple of ways you could send data from server-side, so NodeJS, to client-side - which I assume in your case would be some JavaScript file like main.js that handles DOM manimulation.
So, the 1st way you could send data is through a templating engine like Handlebars, for example. There is an easy to use module for express you could get here: hbs.
Now to quickly summarize how an engine like that works, we are basically sending an HTML file like you probably saw in the tutorials, however, a templating engine like Handlebars allows us to send actual data with that file dynamically, so what we would do is render a specific Handlebars template (which in core is just HTML), and pass in a JavaScript object to the render call which would contain all the data you want to pass into that file and then access it in the .hbs file.
So on the server-side, we would write something like this, assuming we have a file called home.hbs and set up Handlebars as the templating engine:
router.get('/home', function(req,res) {
var dataToSendObj = {'title': 'Your Website Title', 'message': 'Hello'};
res.render('home',dataToSendObj);
});
And access in home.hbs like this:
<html>
<header>
{{title}}
</header>
<body>
message from server: {{message}}
</body>
</html>
Now, the issue with this approach is that if you wanted to update the data on the page dynamically, without having to reload the page, using a templating engine would not be ideal. Instead, like you said, you would use AJAX.
So, the 2nd way you could send data from your NodeJS server to the front-end of your website, is using an asynchronous AJAX call.
First, add a route to whatever route handler you are using for AJAX to make a call to. This where you have some logic to perhaps access the database, make some checks and return some useful information back to client.
router.get('/path/for/ajax/call', function(req,res) {
// make some calls to database, fetch some data, information, check state, etc...
var dataToSendToClient = {'message': 'error message from server'};
// convert whatever we want to send (preferably should be an object) to JSON
var JSONdata = JSON.stringify(dataToSendToClient);
res.send(JSONdata);
});
Assuming you have some file such as main.js, create an AJAX request with callbacks to listen to certain event responses like this:
var req = new XMLHttpRequest();
var url = '/path/for/ajax/call';
req.open('GET',url,true); // set this to POST if you would like
req.addEventListener('load',onLoad);
req.addEventListener('error',onError);
req.send();
function onLoad() {
var response = this.responseText;
var parsedResponse = JSON.parse(response);
// access your data newly received data here and update your DOM with appendChild(), findElementById(), etc...
var messageToDisplay = parsedResponse['message'];
// append child (with text value of messageToDisplay for instance) here or do some more stuff
}
function onError() {
// handle error here, print message perhaps
console.log('error receiving async AJAX call');
}
To summarize the above approach using AJAX, this would be the flow of the interaction:
Action is triggered on client-side (like button pressed)
The event handler for that creates a new AJAX request, sets up the callback so it knows what to do when the response comes back from the server, and sends the request
The GET or POST request sent is caught by our route handler on the server
Server side logic is executed to get data from database, state, etc...
The new data is fetched, placed into a JSON object, and sent back by the server
The client AJAX's event listener for either load or error catches the response and executes the callback
In the case of a successful response load, we parse the response, and update the client-side UI
Hope this is helpful!

Resources