Kumar Divya Rajat
Kumar Divya Rajat

Reputation: 187

Weird routing behaviour in Angular

before refreshing

I have a Mean app setup where the Angular app resides in the '/dashboard' path. The home page of the app runs just fine. Reloading the app gives back the page the app was on. In fact, even in routes with '/dashboard/anything/anything' routes, the app refreshes just fine. But when I refresh the page in '/dashboard/anything' routes, the angular app does not load app and all I am left with if the views' html. I have tried fixing it in so many ways but cannot find a proper explanation for this weird behaviour.

On refreshing, this happens:

The page I am left with after refreshing.

The routing in my app is as follows:-

angular.module('dashboard', ['ngRoute'])
.config(function ($routeProvider, $locationProvider) {
    $routeProvider

    // route for the dashboard home page
        .when('/dashboard/login', {
            templateUrl: 'dashboard/login/index.html'
        })
        .when('/dashboard', {
            templateUrl: 'dashboard/home/index.html'
        })
        .when('/dashboard/events', {
            templateUrl: 'dashboard/events/index.html'
        })
        .when('/dashboard/events/create', {
            templateUrl: 'dashboard/events/create.html'
        })
        .when('/dashboard/events/report', {
            templateUrl: 'dashboard/events/reports.html'
        })

        .when('/dashboard/users', {
            templateUrl: 'dashboard/users/index.html'
        })
        .when('/dashboard/users/create', {
            templateUrl: 'dashboard/users/create.html'
        })
        .when('/dashboard/users/reports', {
            templateUrl: 'dashboard/users/reports.html'
        })

        .when('/dashboard/images', {
            templateUrl: 'dashboard/media/index.html'
        })
        .when('/dashboard/images/add', {
            templateUrl: 'dashboard/media/create.html'
        })
        .when('/dashboard/categories', {
            templateUrl: 'dashboard/categories/index.html'
        })
        .when('/dashboard/logout', {
            templateUrl: ''

        })
        .otherwise({
            redirectTo: 'dashboard'
        });
    $locationProvider.html5Mode(true);
})

And the routing in node is as follows:-

router.get('/dashboard', function(req, res) {
  res.sendFile('/dashboard/index.html',{ root: path.join(__dirname,  '../public') });
});

router.get('/dashboard/*',function(req, res) {
  console.log("Here");
  res.sendFile('/dashboard/index.html',{ root: path.join(__dirname, '../public') });
});

Update:- More code snippets. I didn't mention earlier that I have two angular apps set up at two different routes. The first app at the root level works like a charm but the one at the /dashboard level has this issue.

APP.JS

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
var router = express.Router();
var index = require('./routes/index');
var users = require('./routes/users');
var events = require('./routes/events');
var sponsors = require('./routes/sponsors');
var image = require('./routes/images');
var dashboard = require('./routes/dashboard');
var login=require('./routes/login.js');
var unless = require('express-unless');
// var router = express.Router();
var config = require('./config.js');
require('./database');
var jwt = require('jsonwebtoken');
var smsRoute=require('./routes/smsApi');
var sendSms=smsRoute.router;
var Models = require('./models/models');
var User = Models.user;
var app = express();
var mailer=require('./mailer/mailer.js');

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'hbs');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));


app.use('/', index);
app.use('/dashboard', dashboard);
app.use('/api/send',sendSms);
app.use('/api/login',login);
app.use('/api/mail',mailer);
app.use('/api/events', events);
app.use('/api/users', users);
app.use('/api/sponsors', sponsors);
app.use('/api/image', image);
app.use('*', index);

app.set('superSecret', config.secret);


// catch 404 and forward to error handler
app.use(function (req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

// error handlers

// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
    app.use(function (err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: err
        });
    });
}

// production error handler
// no stacktraces leaked to user
app.use(function (err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
        message: err.message,
        error: {}
    });
});


module.exports = app;

INDEX.JS

var express = require('express');
var router = express.Router();
var path = require('path');
/* GET home page. */

router.get('/', function (req, res, next) {
    res.sendFile('/app/index.html', {
        root: path.join(__dirname, '../public')
    })
});


module.exports = router;

DASHBOARD.JS

var express = require('express');
var router = express.Router();
var path = require('path');

router.get('/*', function(req, res) {
    res.sendFile('/dashboard/index.html',{ root: path.join(__dirname, '../public') });
});


module.exports = router;

And of the many API routes.

var express = require('express');
var router = express.Router();
var Models = require('../models/models');
var Sponsor = Models.sponsor;



/*----------------Get All Users--------------*/
router.get('/',function(request,response) {

    Sponsor.find({},function(err,sponsors) {
        if(err) 
            return response.status(500).json({message : err.message});
        response.json({ sponsors : sponsors});
        response.end();

    });

});


 /*----------------Get User By Id--------------*/


router.get('/:id',function (request,response) {
    var id=request.params.id;

    Sponsor.find({_id:id},function(err,sponsor) {
        if (err)
            return response.status(500).json({message : err.message});
        response.status(200).json({sponsor:sponsor,message:"Sucess"});
        response.end();

    });
});

router.use(require('./tokenVerify.js'));

/*
 *
 *                                                     Start protected routes
 *-------------------------------------------------------------------------------------------------------------------
 *
 *                                             Route authentication using JSONWEBTOKEN.
 *
 */



/*----------------Create New User--------------*/
router.post('/', function (request, response) {
    var sponsor = request.body;
    Sponsor.create(sponsor,function(err,sponsor) {
        if(err) 
            return response.status(500).json({message : err.message});
        response.json({ sponsor : sponsors , message : "Success"});
        response.end();

    });
});



    /*----------------Update Existing User--------------*/


router.put('/:id', function (request, response) {
    var id = request.params.id;
    var sponsor  = request.body;
    if(sponsor && sponsor._id !== id) 
        return response.status(500).json({error : "The id's do not match.", message : "Failure"});
    sponsor["modifiedDate"]=Date();
    Sponsor.findByIdAndUpdate(id, user, { new : true }, function(err,user) {
        if(err) 
            return response.status(500).json({error : err.message, message : "User Not Found"});
        response.status(200).json({message : "Success"});
        response.end();

    });

});

 /*----------------Delete  Existing User--------------*/

router.delete("/:id",function(request,response) {
    var id = request.params.id;
    Sponsor.findOneAndRemove({_id:id},function(err) {
        if (err) 
          {  return response.status(500).json({error:err.message, message:"Can't Delete User"}); console.log("Error");}
        response.status(200).json({message:"Sucess"});       
        response.end();
    });
})




module.exports = router;

I have tried to refactor the code as much as possible. I am absolutely clueless about what's going wrong. Have done a lot of searching but can't find the answers I need.

Upvotes: 0

Views: 290

Answers (2)

Amulya Kashyap
Amulya Kashyap

Reputation: 2373

here's my app.js file :

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var viewRoute = require('./routes/view'), //defining routes
    apiRoute = require('./routes/api'),

app.set('views', path.join(__dirname, 'views'));  //setting to HTML engine instead of EJS | JADE 
app.engine('html', require('ejs').renderFile);
app.set('view engine', 'html');
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', viewRoute);   //using middleware for routing
app.use('/api', apiRoute);

See I've two things :

  1. View -- Rendering for HTML files
  2. Api -- Code for handling get / post request from views (HTML files)

Now view.js file

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index');
});

router.get('/home', function(req, res, next) {
  res.render('pages/home');
});

router.get('/login', function(req, res, next) {
  res.render('pages/login');
});


router.get('/about', function(req, res, next) {
  res.render('pages/about');
});

module.exports = router;

Now api.js file :

var express = require('express');

module.exports = (function() {

    'use strict';

    var api = express.Router();

    api.get('/home', function(req, res, next) {
      console.log("A GET Request for Home Page\n");
    });


    api.get('/dashboard', function(req, res, next) {
      console.log("A GET Request for About Page\n");
    });

    api.get('/about', function(req, res, next) {
      console.log("A GET Request for About Page\n");
    });

return api;

})();

Now My AngularJs Controller File for routing :

$routeProvider
        .when('/home', {
            templateUrl: '/home',
            controller: 'homeCtrl'
        })
        .when('/login', {
            resolve : {
                'check' : function ($location, $cookies){
                    if ($cookies.get('isAuthenticated') && $cookies.get('current_user')) {
                        $location.path('/dashboard');
                    }
                }
            },
            templateUrl: '/login',
            controller: 'loginCtrl'
        })
        .when('/dashboard', {
            resolve : {
                'check' : function ($location, $cookies){
                    if (!$cookies.get('isAuthenticated') || !$cookies.get('current_user')) {
                        $location.path('/login');
                    }
                }
            },
            templateUrl: '/dashboard',
            controller: 'dashboardCtrl'
        })
        .otherwise('/home');

Now you'll see my controller files where after login only i set users to visit my various routes appending to dashboard and after :

myApp.controller('homeCtrl', function ($interval, $rootScope, $scope) {
    //Displaying HOME page
});

myApp.controller('loginCtrl', function ($scope) {
    //DISPLAYING LOGIN PAGE FOR LOGIN
    //YOUR LOGIN CODE GOES HERE AND AFTER THAT DO:
     $location.path('/dashboard/*'); //depending on you
});

smpApp.controller('aboutCtrl', function ($interval, $rootScope, $scope) {
    //DISPLAYING YOUR ABOUT US PAGE
});

NOTICE Following things Keenly :

  1. Routes are checked every time. Means they authenticated.
  2. Different Files for Viewing HTML File and Handling get/POST request from those files
  3. Controllers are different for each files
  4. Using $location.path to traverse or send user to dashboard.

Thanks & Cheers

Upvotes: 0

Dima Fitiskin
Dima Fitiskin

Reputation: 323

You mixing real file urls (like templates) and pseudo routes for angular. If this is so, when angular attempting to load template file like dashboard/users/reports.html express wildcard route /dashboard/* returns /dashboard/index.html file instead. It`s safer to separate them that way:

In node:

router.use('/templates', express.static(path.join(__dirname, 'path/to/templates')));

router.get('/dashboard', function(req, res) {
  res.sendFile('/dashboard/index.html',{ root: path.join(__dirname,  '../public') });
});

router.get('/dashboard/*',function(req, res) {
  console.log("Here");
  res.sendFile('/dashboard/index.html',{ root: path.join(__dirname, '../public') });
});

In angular:

.when('/dashboard/images', {
    templateUrl: '/templates/dashboard/media/index.html'
})

Upvotes: 1

Related Questions