2016-07-30 7 views
0

Ich verwende Angular 1.3.10, UI-Router 0.2.10 und Express 4.14.0 für einen grundlegenden Reddit-Klon, und ich habe Probleme mit dem Routing.Angular: Neuladen/URL-Navigation wird auf Standardroute zurückgesetzt

My (abgekürzt) Express Routen:

router.get('/api/home', function (req, res, next) { 
    res.render('index', { 
    title: 'Meanit' 
    }); 
}); 

router.get('*', function (req, res, next) { 
    res.redirect('/api/home'); 
}); 

Mein Angular Zustandskonfiguration:

app.config([ 
    '$stateProvider', 
    '$urlRouterProvider', 
    '$locationProvider', 
    function ($stateProvider, $urlRouterProvider, $locationProvider) { 
    $stateProvider 
     .state('home', { 
     url: '/home', 
     templateUrl: '/views/home.html', 
     controller: 'MainCtrl', 
     resolve: { 
      postPromise: [ 
      'posts', 
      function (posts) { 
       return posts.getAllPosts(); 
      } 
      ] 
     }      
     }) 
     .state('posts', { 
     url: '/posts/{id}', 
     templateUrl: '/views/posts.html', 
     controller: 'PostsCtrl', 
     resolve: { 
      post: [ 
      '$stateParams', 
      'posts', 
      function ($stateParams, posts) { 
       return posts.getPost($stateParams.id); 
      } 
      ] 
     } 
     }) 
     .state('register', { 
     url: '/register', 
     templateUrl: '/views/register.html', 
     controller: 'AuthCtrl', 
     onEnter: [ 
      '$state', 
      'auth', 
      function ($state, auth) { 
      if (auth.isLoggedIn()) 
       $state.go('home') 
      } 
     ] 
     }) 
     .state('login', { 
     url: '/login', 
     templateUrl: '/views/login.html', 
     controller: 'AuthCtrl', 
     onEnter: [ 
      '$state', 
      'auth', 
      function ($state, auth) { 
      if (auth.isLoggedIn()) 
       $state.go('home') 
      } 
     ] 
     }); 

    $locationProvider.html5Mode(true); 
    $urlRouterProvider.otherwise('home'); 
    } 
]); 

Meine Ordnerhierarchie sieht wie folgt aus: Alle

meanit 
    public 
    js 
     app.js (Angular) 
    routes 
    index.js (Express routes) 
    views (Angular templates) 
    index.html 
    home.html 
    posts.html 
    register.html 
    login.html 
    server.js 

die Routen wie vorgesehen , aber wenn ich die Seite während einer der Routen neu lade oder direkt zur URL der Route navigiere (/ posts/579d17934b0f5f6b2ff5c72c), ich werde zuerst nach/api/home über Express (beabsichtigt, denke ich) und dann nach/home durch Angular statt der/posts/579d17934b0f5f6b2ff5c72c Route (nicht beabsichtigt) umgeleitet.

Wie erzwinge ich URL-Navigation/Neuladen, um auf der Unterroute zu bleiben?

(Ich habe bei AngularJS. Retain state after page reload sehe, aber ich verstehe nicht, wie die URL Parsing einrichten/wie Sie den Code aus der akzeptierten Antwort anzupassen mein Projekt zu passen.)

+0

Wie gehen Sie Ihre statische Ressourcen (Javascript, CSS, HTML, Bilder usw.)? Dienen sie Express oder benutzen Sie einen anderen Webserver wie nginx? – kennasoft

+0

Nicht zu vertraut mit Express, aber es scheint mir, dass Sie nicht möchten, dass Express die URL umleiten. Wenn express Sie an/api/home sendet, erkennt angular das nicht, weil es sich nicht um einen Status handelt. Sie landen also unter/home –

+0

@kennasoft: Ich stehe für die Statik mit Express (öffentliche und Ansichtsordner)). –

Antwort

0

scheint Ihr Problem mit Express ist. Ihr Catchall macht eine res.redirect(), die, denke ich, die Browser-URL aktualisiert. Ich schlage vor, Sie tun einfach eine einfache sendfile() oder render(), anstatt redirect().

Ihr Express Server catchall Route sollte sich ändern:

//This is assuming the index.html file exists on the same directory the server is launched from 
router.get('*', function (req, res, next) { 
    res.render('index', { 
     title: 'Meanit' 
    }); 
}); 
+0

Du hast absolut recht! Ich habe das Express-Routing geändert, um res.render direkt zu verwenden, anstatt zurück zur/api/home-Route umzuleiten, und jetzt funktioniert es perfekt. Danke für deine Hilfe! –

+0

Wir sind froh, dass wir das Problem endlich gefunden haben und Sie können mit dem Erstellen Ihrer App fortfahren. – kennasoft

0

Ich hatte ein ähnliches Problem als ich eines meiner angularjs Projekte startete. In meinem Fall hatte ich 2 verschiedene Server laufen; eine für die API und die andere für die Bereitstellung statischer Dateien. Hier ist, was ausdrücken meine statische Server wie folgt aussieht:

server.js

//server.js 

var express = require('express'); 

var app = express(); 

//use very specific paths to the different resource folders 
app.use('/js', express.static('public/js')); 
app.use('/css', express.static('public/css')); 
app.use('/img', express.static('public/img')); 
app.use('/views', express.static('public/views')); 
app.use('/bower_components', express.static('public/bower_components')); 

var port = process.env.PORT || 80; 
var staticExtensions = ['css','js','png','gif','jpg','woff','woff2','ttf','map']; 
var deeperPaths = ['/posts']; //an array of deeper paths that need special treatment 

//cater specifically for post, since it's deeper than other paths (relative to the other assets /css, /js etc) 
app.get('/posts/:postId', function(req,res){ 
    console.log('fetching matched request: '+ req.path + '...'); 
    res.sendFile(__dirname +'/public/index.html'); 
}); 

//any other request returns the index.html file, where angularjs routing takes over 
app.get('*', function(req, res) { 
    console.log('fetching '+ req.path + '...'); 
    var filePath = __dirname +'/public/index.html'; 

    var requestPath = req.path.split('?')[0]; 
    var fileExtension = requestPath.split('.').pop(); 
    //if it's a static resource make relative to /public 
    if(staticExtensions.lastIndexOf(fileExtension)>-1){ 
     deeperPaths.forEach(function(path, index){ 
      //this is not a very reliable test, but it works for now 
      if(req.path.indexOf(path)===0){ 
       filePath = __dirname + '/public' + req.path.replace(path, ''); 
      } 
     }); 
    } 
    res.sendFile(filePath); // load our public/index.html file 
}); 

// START THE SERVER 
app.listen(port); 
console.log('Website started on port ' + port); 

Hope this helps ...

+0

Leider hat meine App die gleiche Catch-All (mit Express-Router) und es löst das Problem nicht. Ich bin mir ziemlich sicher, dass es ein Angular-Problem ist, den Routenstatus nicht zu speichern. –

+0

Es ist nicht möglich, dass der Status noch vorhanden ist, wenn die gesamte Seite neu geladen wurde. Möglicherweise möchten Sie über die Netzwerkregisterkarte der Chrome-Entwicklungstools überprüfen, ob der Server nicht den falschen Inhalt zurückgibt. Mir ist in meinem Fall aufgefallen, dass, wenn die angeforderte URL einen Schritt tiefer als die Indexdatei ist (z. B./posts/{id}), alle meine statischen Ressourcen den Inhalt der index.html-Datei zurückgeben, was der Fallback ist. Aus diesem Grund müssen die spezifischen Pfade zu jedem Ressourcentyp zugeordnet werden. – kennasoft

+0

Bitte werfen Sie einen Blick auf die modifizierte Antwort oben. Ich weiß, dass es eine bessere, Standardlösung für dieses Problem geben sollte, aber das hat für mich funktioniert, bis ich mit nginx auf die Statik umgestellt habe. Ich habe diesen Code gerade in meinem Repo gefunden. Als ich merkte, dass es mit solchen eckigen URLs unordentlich umgehen würde, wechselte ich zu nginx. – kennasoft

Verwandte Themen