I have an app with a service which wraps my API calls:
var ConcernService = {
...
get: function (items_url, objId) {
var defer = $q.defer();
I managed to handle 404 without using $urlRoutProvider
since I'm only using states by testing $state.transistion
:
angular.module("app", []).run(["$state", "$rootScope", function($state, $rootScope) => {
$rootScope.$on("$locationChangeSuccess", function() {
if (!$state.transition) {
$state.go("404");
}
});
}]);
The otherwise()
rule is only invoked when no other route matches. What you really want is to intercept the $stateChangeError
event, which is what gets fired when something goes wrong in a state transition (for example, a resolve failing). You can read more about that in the state change event docs.
The simplest implementation for what you're trying to do would be something like this:
$rootScope.$on('$stateChangeError', function(event) {
$state.go('404');
});
Also, since $http
itself is built on promises (which resolve
resolves), your ConcernService
method can be simplified down to a one-liner (I realize you expanded it for debugging purposes, but you could have just as easily chained it, just FYI):
var ConcernService = {
get: function (items_url, objId) {
return $http.get(api_url + items_url + objId);
}
}
You can also try something like this and see if it works for you. You may need to adjust to your needs:
.state('otherwise', {
abstract: true,
templateUrl: 'views/404.html'
})
.state('otherwise.404', {
url: '*path',
templateUrl: 'views/404.html'
})
The $urlRouterProvider only works like a $watch to $location and if the actual URL matches one of the rules defined in the .config() function then it will redirect to the specified route.
Here's what I recommend, define "/404/" as a state:
$stateProvider.state('404', {
url:'/404/',
views:{
...
}
});
And inside the reject() function move to 404 state
if(status == '404'){
$state.transitionTo('404');
}
You will have to add ui-router as dependency of the project module and use the $state provider in your controller in order to be able to use $state.transitionTo()
Here's some info: https://github.com/angular-ui/ui-router/wiki/Quick-Reference#statetransitiontoto-toparams--options
$urlRouterProvider.otherwise('/page-not-found');
.state('error', {
url: "/page-not-found",
templateUrl: "templates/error.html",
controller: "errorController"
})
Will handle your page not found problem.
If you want to raise 404 found purposefully use the state or url. We have created a separate controller just if you want to perform any operations.
I differ between two 404 states:
Server:
Client:
Code for Angular UI-Router state:
$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');
}
And why I used $injector
instead of $state
is explained here.