2014-04-24 9 views
13

ich eine App mit einem Dienst haben, die meine API-Aufrufe Wraps:AngularJS UI-Router Handhabung 404s

var ConcernService = { 
    ... 
    get: function (items_url, objId) { 
     var defer = $q.defer(); 
     $http({method: 'GET', 
      url: api_url + items_url + objId}). 
      success(function (data, status, headers, config) { 
       defer.resolve(data); 
      }).error(function (data, status, headers, config) { 
       console.log('ConcernService.get status',status); 
       defer.reject(status); 
      }); 
     return defer.promise; 
    }, 

und ich bin mit UI-Router zwischen den Staaten zu überführen:

concernsApp 

    .config(function ($stateProvider, $urlRouterProvider) { 

     $urlRouterProvider.otherwise("/404/"); 


     $stateProvider.state('project', { 
     url: '/project/:projectId/', 
     resolve: { 
      project: function ($stateParams, ConcernService) { 
       return ConcernService.get('projects/', $stateParams.projectId); 
      }, 
     }, 
     views: { 
      ... 
     } 
    }); 

I‘ Ich bin von der Verwendung des normalen AngularJS-Routers entfernt und habe Schwierigkeiten zu verstehen, wie man 404s implementiert. Ich kann die ConcernService Status console.log als abgelehnt, aber wie sehe ich das im Zustand Router?

Jede Hilfe sehr geschätzt.

Antwort

22

Die otherwise() Regel wird nur aufgerufen, wenn keine andere Route übereinstimmt. Was Sie wirklich wollen, ist das Abfangen des $stateChangeError-Ereignisses, das ausgelöst wird, wenn bei einem Statuswechsel etwas schief geht (z. B. eine fehlgeschlagene Lösung). Sie können mehr darüber in der state change event docs lesen.

Die einfachste Implementierung für das, was Sie versuchen, etwas zu tun wäre:

$rootScope.$on('$stateChangeError', function(event) { 
    $state.go('404'); 
}); 

Da auch $http sich auf Versprechen (die resolve Entschlüssen), Ihre ConcernService Methode nach unten vereinfacht werden kann gebaut zu einem Einzeiler (ich weiß, Sie es für Debugging-Zwecke erweitert, aber man könnte genauso gut angekettet es haben, nur FYI):

var ConcernService = { 

    get: function (items_url, objId) { 
    return $http.get(api_url + items_url + objId); 
    } 
} 
+0

Richtig, der Umgang mit dem 404 macht durchaus Sinn. Mit dem $ http allerdings, wenn ich es wie Sie implementieren, wenn nicht funktionieren wird, da 'objId' von '$ stateParams' kommt und noch nicht aufgelöst ist. Ist das nicht die Methode der "Aufschiebung"? –

+0

Ich bin nicht wirklich sicher, was du meinst, aber wenn du '$ stateParams' in eine resolve- oder' onEnter'-Funktion injizierst, erhältst du eine lokale Kopie, die die Parameter für den Status darstellt, in den der Übergang stattfindet. –

+0

@NateAbele Darf ich fragen, wie Sie $ State in den Event-Handler injiziert haben: $ stateChangeError? Da ich einen Fehler habe: 'undefined $ state' von deinem Beispiel. – Roylee

2

Der $ urlRouterProvider funktioniert nur wie ein $ watch to $ -Standort und wenn die tatsächliche URL mit einer der in der .config() - Funktion definierten Regeln übereinstimmt, wird er auf die angegebene Route umgeleitet.

Hier ist, was ich empfehlen, definieren "/ 404 /" als Staat:

$stateProvider.state('404', { 
    url:'/404/', 
    views:{ 
     ... 
    } 
}); 

Und im Inneren des ablehnen() Funktion Bewegung bis 404 Zustand

if(status == '404'){ 
    $state.transitionTo('404'); 
} 

Sie müssen ui hinzufügen -router als Abhängigkeit des Projektmoduls und verwenden Sie den $ state-Provider in Ihrem Controller, um $ state.transitionTo() verwenden zu können

Hier sind einige Informationen: https://github.com/angular-ui/ui-router/wiki/Quick-Reference#statetransitiontoto-toparams--options

+0

In meinem Code Status eine 'rejected' Eigenschaft zu haben, scheint nicht, es entspricht nur zu" 404 '. –

+0

Oh Entschuldigung für die Verwirrung, ich habe es einfach so als Beispiel, lassen Sie mich den Code aktualisieren. –

3

können Sie auch so etwas wie dies versuchen und sehen, ob es wor ks für dich.Möglicherweise müssen Sie an Ihre Bedürfnisse anpassen:

.state('otherwise', { 
    abstract: true, 
    templateUrl: 'views/404.html' 
}) 
.state('otherwise.404', { 
    url: '*path', 
    templateUrl: 'views/404.html' 
}) 
+3

Ich verstehe nicht, warum Sie diese Zusammenfassung brauchen Route, können Sie das mit einem Staat erreichen? –

+0

Es funktionierte für mich ohne die abstrakte Route. Ich habe nur '.state ('notFound' {url: '* Pfad', templateUrl: 'views/404.html' })' – rjmunro

6

ich unterscheiden zwischen zwei 404 Staaten:

Server:

  • zeigen Seite 404 je nach Server-Antwort HTTP-Code 404
  • wichtig zu definieren keine URL, so dass Benutzer auf URL bleibt, wo der Fehler aufgetreten ist

Kunde:

  • wird URL nicht von Winkel ui Router (keiner von definierten URLs)

-Code für Angular UI-Router Zustand gefunden:

$stateProvider 
    .state('404server', { 
    templateUrl: '/views/layouts/404.html' 
    }) 
    .state('404client', { 
    url: '*path', 
    templateUrl: '/views/layouts/404.html' 
    }); 

Code in $httpProvider Interceptor:

if(response.status === 404) { 
    $injector.get('$state').go('404server'); 
} 

Und warum ich $injector statt $state verwendet wird, erklärt here.

0

$urlRouterProvider.otherwise('/page-not-found');

.state('error', { 
    url: "/page-not-found", 
    templateUrl: "templates/error.html", 
    controller: "errorController" 
}) 

Wird Ihre Seite nicht gefunden Problem behandeln.

Wenn Sie gezielt 404 gefunden haben, verwenden Sie den Status oder die URL. Wir haben einen separaten Controller nur erstellt, wenn Sie irgendwelche Operationen ausführen möchten.

1

schaffte ich 404 zu handhaben, ohne $urlRoutProvider zu verwenden, da ich nur Staaten bin mit von $state.transistion Prüfung:

angular.module("app", []).run(["$state", "$rootScope", function($state, $rootScope) => { 
    $rootScope.$on("$locationChangeSuccess", function() { 
     if (!$state.transition) { 
      $state.go("404"); 
     } 
    }); 
}]);