Handle routes when using Angular combined with Express (Node.js) - javascript

I have the following config in angular
.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider
.when('/', {
templateUrl: '../pages/main.html',
controller: 'RMController',
controllerAs: 'rm'
})
.when('/:user', {
templateUrl: '../pages/emp-details.html'
})
$locationProvider.html5Mode({
enabled: true,
requireBase: false
});
This works fine if click on something in main.html, which then takes me to the emp-details.html.
But, if I explicitly type localhost:8080/1234 (emp-details.html with param), express has never heard of that route.
What is the best way to handle this kind of relationship?
My routes looks like this:
module.exports = function(app, schema) {
//Finds all users
app.get('/api/users', function(req, res){
schema.getEmployees()
.then(function(results) {
res.json(results);
}, function(err) {
console.log(err);
if (err) res.json(err);
});
});
app.get('/api/users/:user', function(req, res) {
schema.getSpecificEmployee(req.params.user)
.then(function(results) {
res.json(results);
}, function(err) {
console.log(err);
if (err) res.json(err);
});
});
//Our default path: index.html
app.get('*', function(req, res){
res.sendFile(path.join(__dirname + '/public/index.html'));
});
}

Try doing this:
.when('/:user', {
url: '/emp-detail', //add this line
templateUrl: '../pages/emp-details.html'
})
Now if you do localhost:8080/#/emp-detail, you should see the emp-details.html page.
By using localhost:8080/#/xyz u should be able to access your routes.
Hope this works!!!

Related

Express redirects to wrong view after passport authentication

I'm having quite the time figuring out why the URL is updating but it goes to the wrong view.
When a user is authenticated with passport, the URL updates to my code (/clients) but the view goes back to the homepage view.
After the user is authenticated, i'd like them to be redirected to my angular app.
folder structure
server
--config
-auth
-express
-mongoose
-passport
-routes
--controllers
--data
--utils
--views
-client (ng app)
-css
-js
-views
index.jade (angular app index)
-shared
layout.jade
-users
login.jade
index.jade (express index)
express.js
app.set('view engine', 'jade');
app.set('views', config.rootPath + '/server/views/');
auth.js
login: function(req, res, next) {
var auth = passport.authenticate('local', function(err, user) {
if (err) return next(err);
if (!user) {
req.session.error = 'Invalid Username or Password!';
res.redirect('/login');
}
req.logIn(user, function(err) {
if (err) return next(err);
res.redirect('/client');
console.log();
})
});
auth(req, res, next);
},...
Routes.js
var auth = require('./auth'),
controllers = require('../controllers');
module.exports = function(app) {
app.get('/register', controllers.users.getRegister);
app.post('/register', controllers.users.createUser);
app.post('/login', auth.login);
app.get('/logout', auth.logout);
app.get('/login', controllers.users.getLogin);
app.get('/', function (req, res) {
res.render('index', {currentUser: req.user});
});
app.get('*', function (req, res) {
res.render('index', {currentUser: req.user});
});
};
If anyone can point me in the right direction, i'd greatly appreciate it.
Add a route
app.get('/client', function (req, res) {
res.render('client/index', {currentUser: req.session.user});
});

Reconciling Express (Passport) and AngularJS Routes

I am building a MEAN-stack application and am finally getting to the point of creating a user authentication. To do so, I followed this tutorial: http://code.tutsplus.com/tutorials/authenticating-nodejs-applications-with-passport--cms-21619
Now, when I incorporate this into my project it works, but only partially. Namely, it seems that the only page I can navigate to properly is the app's home page. If I click on any links or type something other than home in the address bar, it takes me back to the login screen.
What are some possible reasons for that?
My routes/index.js file looks as follows:
var express = require('express');
var router = express.Router();
var isAuthenticated = function (req, res, next) {
// if user is authenticated in the session, call the next() to call the next request handler
// Passport adds this method to request object. A middleware is allowed to add properties to
// request and response objects
if (req.isAuthenticated())
return next();
// if the user is not authenticated then redirect him to the login page
res.redirect('/');
}
module.exports = function(passport){
/* GET login page. */
router.get('/', function(req, res) {
// Display the Login page with any flash message, if any
res.render('index', { message: req.flash('message') });
});
/* Handle Login POST */
router.post('/login', passport.authenticate('login', {
successRedirect: '/home',
failureRedirect: '/',
failureFlash : true
}));
/* GET Registration Page */
router.get('/signup', function(req, res){
res.render('register',{message: req.flash('message')});
});
/* Handle Registration POST */
router.post('/signup', passport.authenticate('signup', {
successRedirect: '/home',
failureRedirect: '/signup',
failureFlash : true
}));
/* GET Home Page */
router.get('/home', isAuthenticated, function(req, res){
res.render('home', { user: req.user });
});
/* Handle Logout */
router.get('/signout', function(req, res) {
req.logout();
res.redirect('/');
});
return router;
}
I also have some AngularJS routes specified in another file (application worked perfectly with these before I started adding authentication).
app.config(['$routeProvider', function($routeProvider){
$routeProvider
.when('/', {
templateUrl: 'partials/home.html',
controller: 'HomeCtrl'
})
.when('/calendar',{
templateUrl: 'partials/calendar.html',
//controller: 'Calendar'
})
.when('/add-activity', {
templateUrl: 'partials/activity-form.html',
controller: 'AddActivityCtrl'
})
.when('/activity/:id',{
templateUrl: 'partials/activity-form.html',
controller: 'EditActivityCtrl'
})
.when('/activity/delete/:id', {
templateUrl: 'partials/activity-delete.html',
controller: 'DeleteActivityCtrl'
})
.otherwise({
redirectTo: '/'
});
}]);
Is there something I am missing?
P.S. I noticed that currently my URL of home page is
http://localhost:3000/home#/
whereas previously it was
http://localhost:3000/#/
I added "home" to differentiate from "/" which is the authentication page; however, I am unsure about how "#" is tacked onto the path in the first quote.
I was able to resolve this as follows. I changed the Express routing to contain a
"login"
route and changed the home route to just
"/"
As a result, the home path became
http://localhost:3000/#/
The hash sign is tacked on by and for the Angular. From my understanding, the Angular treats such path as "/". Then, the remaining routing is done by Angular and I have a single-page AngularJS app.
Working code:
Express
var express = require('express');
var router = express.Router();
module.exports = function(passport){
var isAuthenticated = function (req, res, next) {
// if user is authenticated in the session, call the next() to call the next request handler
// Passport adds this method to request object. A middleware is allowed to add properties to
// request and response objects
if (req.isAuthenticated()){
//console.log(next());
return next();
}
// if the user is not authenticated then redirect him to the login page
res.redirect('/login');
}
/* GET login page. */
router.get('/login', function(req, res) {
// Display the Login page with any flash message, if any
res.render('login', { message: req.flash('message') });
});
/* Handle Login POST */
router.post('/login', passport.authenticate('login', {
successRedirect: '/',
failureRedirect: '/login',
failureFlash : true
}));
/* GET Registration Page */
router.get('/signup', function(req, res){
res.render('register',{message: req.flash('message')});
});
/* Handle Registration POST */
router.post('/signup', passport.authenticate('signup', {
successRedirect: '/',
failureRedirect: '/signup',
failureFlash : true
}));
/* GET Home Page when logged in */
router.get('/', isAuthenticated, function(req, res){
res.render('index', { user: req.user });
});
/* GET Home Page */
router.get('/', isAuthenticated, function(req, res){
res.render('index', { user: req.user });
});
/* Handle Logout */
router.get('/signout', function(req, res) {
req.logout();
res.redirect('/login');
});
return router;
}
Working code: Angular
app.config(['$routeProvider', function($routeProvider){
$routeProvider
.when('/', {
templateUrl: 'partials/home.html',
controller: 'HomeCtrl'
})
.when('/calendar',{
templateUrl: 'partials/calendar.html',
//controller: 'Calendar'
})
.when('/add-activity', {
templateUrl: 'partials/activity-form.html',
controller: 'AddActivityCtrl'
})
.when('/activity/:id',{
templateUrl: 'partials/activity-form.html',
controller: 'EditActivityCtrl'
})
.when('/activity/delete/:id', {
templateUrl: 'partials/activity-delete.html',
controller: 'DeleteActivityCtrl'
})
.otherwise({
redirectTo: '/'
});
}]);

Client Side Routhing with Angular on Node.js & Express

I'm using Node & Express on the server side, and Angular on the client side.
But I can't implement Angular Client-Side routing. My Angular router looks like this:
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/blogs', {
templateUrl: 'partials/blogs',
controller: 'BlogController'
}).
when('/news', {
templateUrl: 'partials/news',
controller: 'NewsController'
}).
otherwise({redirectTo: '/'});
}]);
This is my server routes:
app.use('/',routes.index);
app.use('/partials/:filename',routes.partials);
And my index.js:
exports.partials = function(req, res){
var filename = req.params.filename;
if(!filename) return;
res.render("partials/" + filename );
};
exports.index = function(req, res){
res.render('index');
};
But instead of presenting the partials, I get the index page for every URL
What am I doing wrong?
You have to create a route like this:
router.get('*', function(req, res){
res.render('layout');
});
In layout.jade you can initialize your routes:
script(src='https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js')
script(src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.5/angular-route.js')
script(src='https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular-resource.min.js')
script(src='/javascripts/app.js')
App.js:
var app = angular.module('app', ["ngRoute"]);
app.config(['$routeProvider', function($routeprovider){
$routeprovider.
when('/', {
template: 'Ok'
})
}]);

MEAN Stack routing issue, angular routing does not work

I have my routes.js
module.exports = function(app) {
//I can't use this because angular routing does not work
/*app.get('*', function(req, res) {
res.sendfile('./public/index.html');
});*/
app.get('/submit', function(req,res){
res.sendfile('./public/submit.html');
});
app.get('/schedule', function(req,res){
res.sendfile('./public/schedule.html');
});
app.get('/requests', function(req,res){
res.sendfile('./public/requests.html');
});
app.get('/tv_left', function(req,res){
res.sendfile('./public/tv_left.html');
});
app.get('/tv_center', function(req,res){
res.sendfile('./public/tv_center.html');
});
app.get('/tv_right', function(req,res){
res.sendfile('./public/tv_right.html');
});
app.get('/', function(req, res){
res.sendfile('./public/index.html');
});
};
and my appRoutes.js like this
angular.module('appRoutes', []).config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider
// home page
.when('/', {
templateUrl: 'index.html',
controller: 'LoginController'
})
.when('/submit', {
templateUrl: 'submit.html',
controller: 'SubmitController'
});
$locationProvider.html5Mode(true);
}]);
basicly if I use app.get('*'), then any request will go back to index.html, eventhough the url changed.
That's because express handles routes in the order they are defined. If you want index.html as a catch-all route, move it to the bottom of the function.
Further reading: https://www.safaribooksonline.com/blog/2014/03/10/express-js-middleware-demystified/

Angular - 404 when directly visiting localhost:8080/somePage, but OK on href link?

Only after adding CRUD to my angular controller and service do I get a 404 error when I visit localhost:8080/somePage directly..
Cannot GET /somePage
The href links in my navbar that point to the same URL are still working though!
<li>somePage</li>
Some admin pages won't have page links though, so I need to get to them directly. Any suggestions?
Going to look at the API directly via localhost:8080/api/stuff does display the json:
[ {
"text": "item 1",
"done": false,
"id": "53402c4390dfad962a000001",
"_v": 0 } ]
Here's my appRoutes.js
angular.module('appRoutes', []).config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
$routeProvider
// home page
.when('/', {
templateUrl: 'views/home.html',
controller: 'mainController'
})
//
.when('/somePage', {
templateUrl: 'views/somePage.html',
controller: 'mainController'
});
$locationProvider.html5Mode(true);
}]);
Here's the node+express server.js:
// set up ======================================================================
var express = require('express');
var app = express(); // create our app w/ express
var mongoose = require('mongoose'); // mongoose for mongodb
var port = process.env.PORT || 8080; // set the port
var database = require('./config/database'); // load the database config
// configuration ===============================================================
mongoose.connect(database.url); // connect to mongoDB database on modulus.io
app.configure(function() {
app.use(express.static(__dirname + '/public')); // set the static files location /public/img will be /img for users
app.use(express.logger('dev')); // log every request to the console
app.use(express.bodyParser()); // pull information from html in POST
app.use(express.methodOverride()); // simulate DELETE and PUT
});
// routes ======================================================================
require('./app/routes.js')(app); // load the routes
// listen (start app with node server.js) ======================================
app.listen(port);
console.log("App listening on port " + port);
And here's the Node.js routes.js, per Iqbal Fauzi's comment..
// load the stuff model
var Stuff = require('./models/stuff');
// expose the routes to our app with module.exports
module.exports = function(app) {
// api ---------------------------------------------------------------------
// get all the stuff
app.get('/api/stuff', function(req, res) {
// use mongoose to get all the stuff in the database
Stuff.find(function(err, stuff) {
// if there is an error retrieving, send the error. nothing after res.send(err) will execute
if (err)
res.send(err)
res.json(stuff); // return all the stuff in JSON format
});
});
// create stuff and send back all the stuff after creation
app.post('/api/stuff', function(req, res) {
// create stuff, information comes from AJAX request from Angular
Stuff.create({
text : req.body.text,
done : false
}, function(err, stuff) {
if (err)
res.send(err);
// get and return all the stuff after you create another
Stuff.find(function(err, stuff) {
if (err)
res.send(err)
res.json(stuff);
});
});
});
// delete stuff
app.delete('/api/stuff/:stuff_id', function(req, res) {
Stuff.remove({
_id : req.params.stuff_id
}, function(err, stuff) {
if (err)
res.send(err);
// get and return all the stuff after you create another
Stuff.find(function(err, stuff) {
if (err)
res.send(err)
res.json(stuff);
});
});
});
// application -------------------------------------------------------------
app.get('/', function (req, res) {
res.sendfile('./public/index.html'); // load the single view file (angular will handle the page changes on the front-end)
});
// commented out for testing this problem.. because this otherwise redirects..
// app.get('*', function (req, res) {
// res.redirect('/'); // redirect to / and index.html will be served
// });
};
Uncomment your app.get('*', function (req, res) and instead of redirecting it to '/' you will better return the index.html file, let AngularJS handle the browser URL for you.
app.get('*', function (req, res) {
res.sendfile('./public/index.html');
});

Categories

Resources