How do I update A Jade Template form an ajax post? - node.js

I have set up a basic node.js web-app using express with the default view engine jade.
When the User first loads the page the following occurs
app.get('/', function(req, res){
res.render('index', {
title: 'Test',
mode: "user"
});
});
What i cannot work out is how to then change the parameter I initially passed into the jade template from a ajax call.
app.post('/', function(req, res){
console.log(req.body.list);
res.redirect('back');
// I imagine the code needs to go here and look somewhat like the following
//
// res.?update-view({
// mode: "admin"
// });
});
If anyone has had experience with this working your input would be appreciated.

I'm not exactly sure what you're after, but if it's updating the page with the results of an AJAX call (which does not refresh or otherwise reload the page) then you'll have to use client-side JavaScript. jQuery's load() or post() should be able to handle that.
Alternatively, if you are not using AJAX but instead performing a normal form submit, you have a couple of options. One, you can keep your redirect in and use Express/Connect's Sessions system to determine what is used for the get request, or two you can replace the redirect with another res.render of the index.jade page and include the variable you want to change.
It should be understood that after either of these takes place, node.js relinquishes control of the web page to the browser, unless you specifically set up architecture for communication. There are currently no controls in node.js to force updates or page changes down to the client. Except via socket connections or unless otherwise polled by the client itself (such as in the first example involving jQuery).

Assuming you want to display the same page, with other "mode"
// set the page title for all requests
app.locals({ title: 'Test' });
// GET request
app.get('/', function(req, res){
res.render('index', {
// displays the default "user" mode
mode: 'user'
});
});
// when POST is submited
app.post('/', function(req, res){
// this is the param given by the user
console.log(req.body.list);
// now render the same page
res.render('index', {
// with mode set to the the given parameter
mode: req.body.list
});
});

You could use something like the following, or if you want to use an AJAX call use jQuery ajax as long as there is a response
Client
script(type="text/javascript")
$(document).ready(function(){
//...AJAX here....
var newValue = #{value} + 10;
});
Server
app.get('/ajax', function(req, res){
//This is where your code and response go
});

Related

In node.js with express, is there a way of changing the url of a link on the fly?

I have a link on a page:
Back
which of course takes the user to '/application-reference'. However, if the session has timed out, I want the user to taken to '/session-ended' instead. Session timed out is detected by the absence of request.session.
I've tried changing the href to send the user back to the same page (i.e. the link is in 'security-code' and takes the user to 'security-code') with the idea that the handling code can look for request.session and decide which page to redirect to, only I can find no way for the code to detect that the page has been called by itself via the back button.
I think the answer is to put something in my express module so that the router.get call that redirects to '/application-reference' will under the right circumstances redirect to '/session-ended'. But I have no idea how to go about this.
I suppose the ideal would be for the '/session-ended' screen to be invoked any time the user clicks on any screen once the session has timed out.
Any suggestions?
Inside your /application-reference-handler you could check if the session on the req-object is still valid. If not redirect the request to /session-ended:
app.get('/application-reference', (req, res) => {
if(!req.session) { // or a more detailed check for the session's validity
return res.redirect("/session-ended");
}
// rest of the handler-code ...
});
An better way to do this is to define a separate middleware to check the user's session - this allows you to reuse this middleware and not having to duplicate the check in your handlers:
function validateSession(req,res,next) {
if(!req.session) { // or a more detailed check for the session's validity
return res.redirect("/session-ended");
}
// all is good, go to the next middleware
next();
});
app.get('/application-reference', validateSession, (req, res) => { ... });

ExpressJS : res.redirect() not working as expected?

I've been struggling for 2 days on this one, googled and stackoverflowed all I could, but I can't work it out.
I'm building a simple node app (+Express + Mongoose) with a login page that redirects to the home page. Here's my server JS code :
app
.get('/', (req, res) => {
console.log("Here we are : root");
return res.sendfile(__dirname + '/index.html');
})
.get('/login', (req, res) => {
console.log("Here we are : '/login'");
return res.sendfile(__dirname + '/login.html');
})
.post('/credentials', (req, res) => {
console.log("Here we are : '/credentials'");
// Some Mongoose / DB validations
return res.redirect('/');
});
The login page makes a POST request to /credentials, where posted data is verified. This works. I can see "Here we are : '/credentials'" in the Node console.
Then comes the issue : the res.redirect doesn't work properly. I know that it does reach the '/' route, because :
I can see "Here we are : root" in the Node console
The index.html page is being sent back to the browser as a reponse, but not displayed in the window.
Chrome inspector shows the POST request response, I CAN see the HTML code being sent to the browser in the inspector, but the URL remains /login and the login page is still being displayed on screen.
(Edit) The redirection is in Mongoose's callback function, it's not synchronous (as NodeJS should be). I have just removed Mongoose validation stuff for clarity.
I have tried adding res.end(), doesn't work
I have tried
req.method = 'get';
res.redirect('/');
and
res.writeHead(302, {location: '/'});
res.end();
Doesn't work
What am I doing wrong? How can I actually leave the '/login' page, redirect the browser to '/' and display the HTML code that it received?
Thanks a million for your help in advance :)
The problem might not lie with the backend, but with the frontend. If you are using AJAX to send the POST request, it is specifically designed to not change your url.
Use window.location.href after AJAX's request has completed (in the .done()) to update the URL with the desired path, or use JQuery: $('body').replaceWith(data) when you receive the HTML back from the request.
If you are using an asynchronous request to backend and then redirecting in backend, it will redirect in backend (i.e. it will create a new get request to that URL), but won't change the URL in front end.
To make it work you need to:
use window.location.href = "/url"
change your async request (in front end) to simple anchor tag (<a></a>)
It's almost certain that you are making an async call to check Mongoose but you haven't structured the code so that the redirect only happens after the async call returns a result.
In javascript, the POST would look like something this:
function validateCredentials(user, callback){
// takes whatever you need to validate the visitor as `user`
// uses the `callback` when the results return from Mongoose
}
app.post('/credentials', function(req, res){
console.log("Here was are: '/credentials'";
validateCredentials(userdata, function(err, data){
if (err) {
// handle error and redirect to credentials,
// display an error page, or whatever you want to do here...
}
// if no error, redirect
res.redirect('/');
};
};
You can also see questions like Async call in node.js vs. mongoose for parallel/related problems...
I've been working on implementing nodemailer into my NextJS app with Express. Was having this issue and came across this. I had event.preventDefault() in my function that was firing the form to submit and that was preventing the redirect as well, I took it off and it was redirecting accordingly.
Add the following in your get / route :
res.setHeader("Content-Type", "text/html")
Your browser will render file instead of downloading it

How can a Sails controller get request history

I am developing a website using Nodejs (with Sails & Passport frameworks). I am wondering how a Sails controller get the request history of a user.
For instance, a user requests for '/', but a controller redirects the user to '/signin'. Then the user requests for '/signin' using res.redirect(). So the request history looks like
'/'
'/signin'.
Now a SignInController handles the request and at the end, it want to redirect the user back to '/'. So the controller should know the history of the user's request. I guess there should be some frameworks which can record request histories and store them using session or something. Could anyone give me some hints about this?
Let me know if I understood well but what you want to do is to redirect the user to whatever URL he was before a login, right?
To do that you can use the policies (which are executed for all requests, only on the methods you want).
What we do here is save the latest position only (Not the entire history)
In api/policies/ensureReturnToUrl:
'use strict';
module.exports = function (req, res, next) {
req.session.returnTo = req.url;
return next();
};
The configuration part look like that in config/policies.js:
'*': ['passport', 'isAuthenticated', 'ensureReturnToUrl'],
AuthController: {
'*': ['passport']
}
You will have to be careful here to put this policy in the right place only. For example, you don't want to have it on you "/signin" methods (That goes against the whole point)
Then, after a successful login, you just have to read the "returnTo" property and redirect the user: (For example in a AuthController)
if (req.session.returnTo) {
res.redirect(req.session.returnTo);
} else {
res.redirect('/');
}
Obviously this need to be adapted for your use case but the policies are definitely what you need.

Node.js Express: passing parameters between client pages

I have a Node.js server. Lets say each client has his name saved on a variable. They switch page and I want each client to mantain their name on a variable.
This would be very easy with a php form, but I can't see how to do it with Node.js
If I do a form like I would do in php, I manage to send the name to the server:
app.post('/game.html', function(req, res){
var user = req.param('name');
console.log(user);
res.redirect('/game.html');
});
But it seems too complicated to then resend it again to each client it's own.
I just started with Node.js, I guess it's a concept error. Is there any easy way to pass a variable from one page in the client to another?
Thanks.
Instead of redirecting to a static file, you have to render the template ( using any engine that ExpressJS supports ):
app.post('/game.html', function(req, res){
var user = req.param('name');
console.log(user);
res.render( 'game.html', { user:user } );
});
( note that .render requires some additonal settings set on app )
Now user variable becomes available in game.html template.
You can use res.render and pass many variables, like that:
res.render('yourPage', {username:username, age:age, phone:phone});

How to dynamically render/load pages in express?

I need to dynamically load/render part of a page in nodejs (v1.8.15) with express (>3.0) framework. Generally, I want to create a single-page app.
I have a menu at the top of the page with links. Clicking on the links will change the content below, as in AJAX page loading.
For example:
>home|login|signup|chat
..content for home..
If I press the 'signup' link:
home|login|>signup|chat
..content for signup..
In express I have routes on the server:
var express = require('express');
var app = express();
app.get('/signup', function(req, res) {
// render signup.jade
res.render('signup');
}
app.post('/signup', function(req, res) {
// .. work with information
if (ok) res.send('ok', 200); else res.send(error, 200);
}
After reading this, I figured out that I should use socket.io. I know sockets well, so it will be easy to send data about 'clicking on link' from the client to the server.
Q1: How do I render/load pages dynamically like I wrote in express?
Yes, I could use AJAX for page loading, but will it work for .post methods in express?
How should I organize my thoughts to create such a site?
By the way, I've read about Derby and SocketStream, but I didn't understand.
Q2: Can I use Derby or SocketStream in my aims (site functions: login, signup, chat)? How?
If SocketStream is what I need, that would be very bad, because Heroku doesn't work with it.
Q1) This is in fact very simple, no need for Socket.io, Derby or whatever. You can call any expess route with any method through ajax, using jQuery makes ajax very easy. In your example, let's suppose your container HTML file has a div with id 'container', which is where you want the ajax-loaded content to go:
$.ajax({ url: 'http://yoursite.com/signup'
, type: 'GET'
, dataType: 'html'
})
.done(function(data) {
$('#container').html(data);
})
.fail(function() {
console.log("Something went wrong!");
});
Express supports all HTTP verbs (GET, POST, PUT etc.). For loading pages dynamically, use GET, then when a user enters some login information you can POST it to an Express route that will tell you if it is valid or not, and you use jQuery to modify the DOM accordingly.
Q2) As said in Q1, no need to use Derby or SocketStream. Plain old jQuery + basic Express will get you where you want!

Resources