6

I am building a simple HTML site using Angular JS ui-router.

I have built a custom 404 page ('www.mysite/#/error/404'), to which the user is redirected if the user types a url like 'www.mysite/#/invalidUrl'. This functionality was achieved by the following code snippet:

$urlRouterProvider
            .when('', '/')
            .when('/home', '/')
            .otherwise('/error/404');

And the following state snippet:

$stateProvider.state('404', {
            parent: 'app',
            url: '^/error/404',
            views: {
                'errorContent@main': {
                    controller: 'error404Controller',
                    templateUrl: 'js/general/templates/error404.html'
                }
            }
        });

I am trying to capture the invalid URL requested by the user to be displayed to the user like below.

The URL you requested cannot be found
Request: www.mysite.com/#/invalidUrl

I have tried listening to '$stateNotFound' event, which only seems to be firing when a specific invalid state is requested. I've also tried to listening to events '$stateChangeStart', '$locationChangeStart', and '$locationChangeSuccess' but couldn't find a way to achieve this functionality.

Is this possible? Please, share your thoughts - thank you

Pasan Ratnayake
  • 495
  • 4
  • 10
  • $stateNotFound fires when requested state is not found. So when you don't have requested state you can catch that state from toState param passed in $stateNotFound fun/event. You need to get your domain url through javascript. combined both will result in what you are looking for. – micronyks Sep 13 '15 at 10:57
  • When an invalid URL is typed into the address bar, it goes through a series of events before reaching into the error state that i explained earlier. However, '$stateNotFound' does not get fired at any time during the process. – Pasan Ratnayake Sep 13 '15 at 11:02
  • That because you have already mentioned when error occurs your are targeting particular state " .otherwise('/error/404')". try to remove it for awhile from routing file and test if $StateNotfound is occurred or not. I guess, it will get fired once you remove "Otherwise" section. – micronyks Sep 13 '15 at 11:09
  • Tried removing the 'otherwise' condition and also tried adding a fake state to otherwise condition like this '.otherwise('/meaningless')'. But still the same – Pasan Ratnayake Sep 13 '15 at 11:26
  • 1
    Have you checked this Q & A: http://stackoverflow.com/questions/23298021/how-not-to-change-url-when-show-404-error-page-with-ui-router ? – Radim Köhler Sep 13 '15 at 13:17
  • Thank you Mr. Radim. That solved it! – Pasan Ratnayake Sep 13 '15 at 16:46

1 Answers1

6

Awesome! Thank you Radim Köhler. I don't know how I didn't land on that thread when I searched but that helped me get the answer.

I changed the answer in that thread to fit my scenario which I am going to leave below for reference to any other users.

$stateProvider.state('404', {
            parent: 'app',
            url: '^/error/404',
            views: {
                'errorContent@main': {
                    controller: 'error404Controller',
                    templateUrl: 'js/general/templates/error404.html'
                }
            }
        });

        $urlRouterProvider
            .when('', '/')
            .when('/home', '/')
            .otherwise(function ($injector, $location) {
                var state = $injector.get('$state');
                state.go('404', { url: $location.path() }, { location: true });
        });

So the magic change was the function defined for 'otherwise' option. I didn't change the URL of the 'error' state. Instead, I used the 'state.go' to activate state '404' and passed the location path as the state parameter.

Setting location=true will take you to the URL of the state, and location=false will not. Whichever way you prefer the invalid URL can be accessed easily now.

Community
  • 1
  • 1
Pasan Ratnayake
  • 495
  • 4
  • 10