简体   繁体   中英

no index.html after reloading angular app

I have an angular.js application with a basic setup like: My index.html renders the static stuff like Top/Sidebar. Inside I have <div ng-view></div> to show the partial html files like for example my home.html

After I log into my application the index.html with it's Controller MainCtrl loads aswell as my home.html with the according HomeCtrl . So everything so far as it should be.

After I implemented a fix (so that reloading wont "forget" the user and I dont get logged out - I based it on the example from http://www.sitepoint.com/implementing-authentication-angular-applications/ ) I tried reloading my page. But now only my home.html loads.

NOTE: I edited my findings below

Which makes sense, here's part of my app.js :

$routeProvider.when('/', {
    templateUrl: 'views/home.html',
    controller: 'HomeCtrl',
    resolve: {
        auth: function ($q, authenticationSvc) {
            var userInfo = authenticationSvc.getUserInfo();
            if (userInfo) {
                return $q.when(userInfo);
            } else {
                return $q.reject({ authenticated: false });
            }
        }
    }
})
.when('/login', {
    templateUrl: 'views/login.html',
    controller: 'LoginCtrl',
    login: true
})

So obviously when I load / the application only shows my home.html . But how can I achieve, what I already have when I enter the page normally after the login?

My main problem seems to be at the moment for me that I'm not quite sure how and why index.html loads fine when I log in. Here's what I do in my LoginCtrl after the SignIn Process is complete:

$location.path("/");

I searched the web for some detailed explainations on this topic, but unfortunately I didn't find anything useful yet. Can someone explain to my why this works in the first place and how I can make it work for page reloading as well? Thank you!

edit I read here ( https://github.com/angular-ui/ui-router/wiki/Frequently-Asked-Questions#how-to-configure-your-server-to-work-with-html5mode ) that I have to change my express configuration. I tried:

app.all('/*', function(req, res, next) {
    res.sendfile('public/index.html', { root: __dirname });
});

I use $locationProvider.html5Mode(true);

But when I login now my page refreshes infintly until it crashes.

edit2: ok, after reading lots on html5mode and how to use it with express I'm quite certain that my Bug is in the Backend, not in the Frontend.

Here are parts of my server.js (express config)

app.use(require('less-middleware')(path.join(__dirname, 'public')));
app.use(express.static(__dirname + '/public'));
app.set('view engine', 'html');
app.set('views', __dirname + '/public/views/');

require('./routes')(app); // contains my other routes

app.get('/', function(req, res) {
    res.render('index');
});
app.get('/views/:name', function (req, res) {
    var name = req.params.name;
    res.render('views/' + name);
});
app.get('*', function(req, res) {
    res.redirect('/');
});

my folder structure:

/server.js
/routes
/public/app.js
/public/index.html
/public/views/home.html
/public/controllers/xxxCtrl.js

I've read many posts on stackoverflow and other sites which basically all say that

app.get('*', function(req, res) {
        res.redirect('/');
    });

should be enough to get this working, but for me it doesn't seem to work.


edit3: A quick summary what my current problem is:

When I reload the page only the partial html like eg home.html is being loaded. Not the full page with index.html . Here's a quick summary of my corrent code:

in the app.js (angular config) I have configured:

$locationProvider.html5Mode(true); 
// I tried my app without html5mode, but then everything breaks - but I need the html5mode anyway
$routeProvider.when('/', {
            templateUrl: 'views/home.html',
            controller: 'HomeCtrl',
            resolve: {
                auth: function ($q, authenticationSvc) {
                    var userInfo = authenticationSvc.getUserInfo();
                    if (userInfo) { return $q.when(userInfo); } 
                    else { return $q.reject({ authenticated: false });}
                }
            }
        })

my authenticationSvc :

.factory("authenticationSvc", ["$http", "$q", "$route", "$window", "$location", function ($http, $q, $route, $window, $location) {
// login, logout
function init() {
        console.log("init");
        if ($window.sessionStorage["userInfo"]) {
            userInfo = JSON.parse($window.sessionStorage["userInfo"]);
        }
    }

    init();

and on the server side, the server.js :

app.get('/:name', function (req, res) {
    var name = req.params.name;
    res.sendFile('views/' + name);
    // res.sendFile(__dirname + '/public/index.html'); // uncommented, since it didn't work
});


require('./routes')(app);

// this is my last route:
app.get('*', function (req, res) {
    res.redirect('/#' + req.originalUrl);
});

from my understanding this "should" be enough configuration for express and angular to work together.

First of all in the template url of your angular routes add a / at the beginning like templateUrl: '/views/home.html' . Since in your express app you are looking for /:name which contains / at the beginning.

Next

// ------
// try adding this

app.get('/*', function (req, res) {
    res.sendFile(__dirname + '/public/index.html'); // uncommented, since it didn't work
});

// Now what this does is that everytime a request is made it will send the index file
// The asterisk will allow anything after it to pass through
// Once it reaches the front end, Angular will process whats after "/"
// It then will make an asynchronous request to the server depending on what
// path is present after "/"
// That is when app.get('/:name'... is called


//------

app.get('/:name', function (req, res) { // This route will be called by angular from the front end after the above route has been processed

    var name = req.params.name;

    // since your template url is /views/home.html in the angular route, req.params.name will be equal to 'views/home.html'. So you will not need to add yet another 'views/' before the variable name
    res.sendFile(name);
    // res.sendFile('views/' + name);
    // res.sendFile(__dirname + '/public/index.html'); // uncommented, since it didn't work
});


require('./routes')(app);

// this is my last route:
app.get('*', function (req, res) {
    res.redirect('/#' + req.originalUrl);
});

Make sure to put all your client side code in the /public folder and make it accessible through express static middleware, in your server.js

app.use(express.static(__dirname+'/public')));

Then add , after defining all the routes

app.route('/*') // this is the last route
.get(function(req, res) {
  res.sendfile(__dirname+ '/public/index.html');
});

on a side-note, __dirname is local to the file you're in, and it always point to the containing folder. so be careful when using __dirname in files that are in sub-folders.

after lots of work, I created a new project, tried the routing explained in eg the links/answers above and then copied my old code. Unfortuntely I never found out what the problem really was. Must have been some tiny part I've been missing to mention in this thread.

Solution if you run into this kind of problem: take a look at the links and try to create a working example project. At least that worked for me.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM