Code


<?php if (!isset($useHtml5Mode)) { $useHtml5Mode = true; } $baseExamplesURL = "/code/examples"; ?> <!DOCTYPE html> <html> <head> <script src="<?php echo $baseExamplesURL ?>/angularjs/angular.js"></script> <script src="<?php echo $baseExamplesURL ?>/angularjs/angular-route.js"></script> <script src="<?php echo $baseExamplesURL ?>/routing/02_RouteService/example/script.js"></script> <script src="<?php echo $baseExamplesURL ?>/routing/02_RouteService/example/<?php echo ($useHtml5Mode ? 'html5' : 'hashbang') ?>/script.js"></script> </head> <body ng-app="<?php echo ($useHtml5Mode ? 'html5Module' : 'hashbangModule') ?>"> <div ng-controller="mainController"> <h3><?php echo ($useHtml5Mode ? "2. HTML5" : "1. Hashbang") ?> mode</h3> <h3>This is the selected view</h3> <div ng-view></div> <h3>Select a view</h3> <strong>1. Simple route with a template URL</strong><br /> <a ng-href="{{localLinksPrefix}}/theviews/viewone">View 1 - URL: /theviews/viewone</a><br /> <br /> <strong>2. Simple route with a template URL returned by a function</strong><br /> <a ng-href="{{localLinksPrefix}}/theviews/viewtwo">View 2 - URL: /theviews/viewtwo</a><br /> <br /> <strong>3. Route with multiple parameters</strong><br /> <a ng-href="{{localLinksPrefix}}/theviews/viewthree/value1/subview1/value2/with/multiple/slashes/subview2/">View 3 - URL: /theviews/viewthree/value1/subview1/value2/with/multiple/slashes/subview2/</a><br /> <br /> <strong>4. Route with optional parameters</strong><br /> <a ng-href="{{localLinksPrefix}}/theviews/viewfour/value1">View 4 - URL: /theviews/viewfour/value1</a><br /> <br /> <strong>5. Simple route with an inline template</strong><br /> <a ng-href="{{localLinksPrefix}}/theviews/viewfive">View 5 - URL: /theviews/viewfive</a><br /> <br /> <strong>6. Route with parameters and with an inline template returned by a function</strong><br /> <a ng-href="{{localLinksPrefix}}/theviews/viewsix/value1/optionalValue2">View 6 - URL: /theviews/viewsix/value1/optionalValue2</a><br /> <br /> <strong>7. Redirect to another route (and add two parameters)</strong><br /> <a ng-href="{{localLinksPrefix}}/theviews/viewseven/value1FromView7?searchParam1=value2FromView7">View 7 - URL: /theviews/viewseven/value1FromView7?searchParam1=value2FromView7</a> (redirects to /theviews/viewfour/value1FromView7/value2FromView7)<br /> <br /> <strong>8. Use a different controller for the view</strong><br /> <a ng-href="{{localLinksPrefix}}/theviews/vieweight/value1/value2">View 8 - URL: /theviews/vieweight/value1/value2</a><br /> <br /> <strong>9. Use a different controller for the view (controller defined inline)</strong><br /> <a ng-href="{{localLinksPrefix}}/theviews/viewnine/value1/value2">View 9 - URL: /theviews/viewnine/value1/value2</a><br /> <br /> <strong>10. Use a different controller for the view and define an alias for it</strong><br /> <a ng-href="{{localLinksPrefix}}/theviews/viewten/value1/value2">View 10 - URL: /theviews/viewten/value1/value2</a><br /> <br /> <strong>11. Resolve (wait for all the promises to be resolved)</strong><br /> <a ng-href="{{localLinksPrefix}}/theviews/vieweleven/2000">View 11 - URL: /theviews/vieweleven/2000</a> (wait 2 seconds before the view appears)<br /> <br /> <strong>12. Invalid view (redirect to the default route and display the default view)</strong><br /> <a ng-href="{{localLinksPrefix}}/theviews/invalidview">Invalid view - URL: /theviews/invalidview</a><br /> <br /> </div> </body> </html>
angular.module("mainModule", ["ngRoute"]) .provider("startupInfo", function () { // Private variables var isHtml5Mode = false; var hashPrefix = ""; var baseURL = "/code/examples/routing/02_RouteService/example"; return { $get: function () { return { getBaseURL: function () { return baseURL; }, getIsHtml5Mode: function () { return isHtml5Mode; }, getHashPrefix: function () { return hashPrefix; } }; }, setURLsConfig: function (isHtml5ModeValue, hashPrefixValue) { isHtml5Mode = isHtml5ModeValue; hashPrefix = hashPrefixValue; } }; }) .provider("routesManager", function ($routeProvider, startupInfoProvider) { // Private variables var routesOutputScope; return { $get: function () { return { setOutputScope: function (outputScope) { routesOutputScope = outputScope; } }; }, configRoutes: function (baseRouteURL) { $routeProvider // 1. Simple route with a template URL .when(baseRouteURL + "/theviews/viewone", { templateUrl: startupInfoProvider.$get().getBaseURL() + "/views/view1.html" }) // 2. Simple route with a template URL returned by a function .when(baseRouteURL + "/theviews/viewtwo", { templateUrl: function () { return startupInfoProvider.$get().getBaseURL() + "/views/view2.html"; } }) // 3. Route with multiple parameters .when(baseRouteURL + "/theviews/viewthree/:param1/subview1/:param2*\/subview2/", { templateUrl: function (params) { routesOutputScope.view3 = { param1: params.param1, param2: params.param2 }; return startupInfoProvider.$get().getBaseURL() + "/views/view3.html"; } }) // 4. Route with optional parameters .when(baseRouteURL + "/theviews/viewfour/:param1?/:param2?", { templateUrl: function (params) { routesOutputScope.view4 = { param1: params.param1, param2: params.param2 }; return startupInfoProvider.$get().getBaseURL() + "/views/view4.html"; } }) // 5. Simple route with an inline template .when(baseRouteURL + "/theviews/viewfive", { template: "<div style=\"background-color: #fcfcfc; border: 1px solid #e1e1e1; text-align: center; width: 200px;\">View 5</div>" }) // 6. Route with parameters and with an inline template returned by a function .when(baseRouteURL + "/theviews/viewsix/:param1/:param2?", { template: function (params) { routesOutputScope.view6 = { param1: params.param1, param2: params.param2 }; return "<div style=\"background-color: #fcfcfc; border: 1px solid #e1e1e1; padding: 6px; width: 250px;\">" + "View 6<br />" + "- param1: {{view6.param1}}<br />" + "- param2: {{view6.param2}}" + "</div>"; } }) // 7. Redirect to another route (and add two parameters) .when(baseRouteURL + "/theviews/viewseven/:param1", { redirectTo: function (params, path, searchParams) { return baseRouteURL + "/theviews/viewfour/" + params.param1 + "/" + searchParams.searchParam1; } }) // 8. Use a different controller for the view .when(baseRouteURL + "/theviews/vieweight/:param1/:param2", { templateUrl: startupInfoProvider.$get().getBaseURL() + "/views/view8.html", controller: "additionalController1" }) // 9. Use a different controller for the view (controller defined inline) .when(baseRouteURL + "/theviews/viewnine/:param1/:param2", { templateUrl: startupInfoProvider.$get().getBaseURL() + "/views/view9.html", controller: function ($scope, $routeParams) { // Store the name of the controller in a variable of the scope $scope.controllerName = "additionalController2"; $scope.param1Value = $routeParams.param1; $scope.param2Value = $routeParams.param2; } }) // 10. Use a different controller for the view and define an alias for it .when(baseRouteURL + "/theviews/viewten/:param1/:param2", { templateUrl: startupInfoProvider.$get().getBaseURL() + "/views/view10.html", controller: "additionalController3", controllerAs: "ctrlAlias" }) // 11. Resolve (wait for all the promises to be resolved) .when(baseRouteURL + "/theviews/vieweleven/:delayTime", { templateUrl: startupInfoProvider.$get().getBaseURL() + "/views/view11.html", controller: "additionalController4", resolve: { // Parametric delay (function that returns a promise) routingDelay: function($route, $q, $timeout) { // Get the delay time from the "delayTime" parameter of the route. // // NOTE: $routeParams cannot be used here because it // still refers to the previous route and will // change only when all the dependencies of the // current route will be resolved; $route.current.params // can be used instead. var delayTime = $route.current.params.delayTime; var deferred = $q.defer(); // Generate a delay $timeout( function () { deferred.resolve("routingDelay function waited for " + delayTime + " milliseconds"); }, delayTime); // Return the promise and the new controller "additionalController4" // will be instantiated only when all the promises defined // inside "resolve" will be resolved (in this example, the promise // returned by the "routingDelay" function is the only one, so // the new controller "additionalController4" will be // instantiated as soon as this promise is resolved). return deferred.promise; }, // "routeParamsAlias" is just an alias for the "$routeParams" service and // will be injected in the controller of this route ("additionalController4"). routeParamsAlias: "$routeParams", // "customFunction"'s result will be injected in the controller // of this route ("additionalController4"). customFunction: function () { return "result from customFunction"; } } }) // 12. Default route (used by the "otherwise" method) .when(baseRouteURL + "/theviews/defaultview", { templateUrl: function () { return startupInfoProvider.$get().getBaseURL() + "/views/defaultview.html"; } }) // 12. Return the route to use in case there are no matches with the previously // defined routes (the default route). .otherwise( { redirectTo: baseRouteURL + "/theviews/defaultview" }); } }; }) .controller("mainController", function ($scope, startupInfo, routesManager) { // Store the name of the controller in a variable of the scope $scope.controllerName = "mainController"; // Set the prefix used with the local links (i.e. links that // point to a path which is relative to the current page). // In HTML5 mode the prefix will be the base URL of the page, // while in hashbang mode the prefix will be "#!". // // The local links in the index HTML page will look like this: // - HTML5 mode: "{{baseURL}}/theviews/firstview" // - hashbang mode: "#!/theviews/firstview" if (startupInfo.getIsHtml5Mode()) { $scope.localLinksPrefix = startupInfo.getBaseURL() + "/html5"; } else { $scope.localLinksPrefix = "#" + startupInfo.getHashPrefix(); } // Set the output scope in routesManager (so we can see some output // to test particular cases). routesManager.setOutputScope($scope); }) .controller("additionalController1", function ($scope, $routeParams) { // Store the name of the controller in a variable of the scope $scope.controllerName = "additionalController1"; // Store the values of the parameters in variables of the scope $scope.param1Value = $routeParams.param1; $scope.param2Value = $routeParams.param2; }) .controller("additionalController3", function ($routeParams) { // Store the name of the controller in a variable of the scope this.controllerName = "additionalController3"; // Store the values of the parameters in variables of the scope this.param1Value = $routeParams.param1; this.param2Value = $routeParams.param2; }) .controller("additionalController4", function ($scope, routingDelay, routeParamsAlias, customFunction) { // Store the name of the controller in a variable of the scope $scope.controllerName = "additionalController4"; // Store in variables of the scope the values // that have to be displayed inside the view. $scope.delayTime = routeParamsAlias.delayTime; $scope.routingDelayResult = routingDelay; $scope.customFunctionResult = customFunction; });
<?php $useHtml5Mode = false; include("../common.php"); ?>
angular.module("hashbangModule", ["mainModule"]) .config(function ($locationProvider, startupInfoProvider, routesManagerProvider) { $locationProvider.html5Mode(false).hashPrefix("!"); // Set the current URLs configuration in the startupInfoProvider // so we can have it also outside the configuration phase. startupInfoProvider.setURLsConfig($locationProvider.html5Mode(), $locationProvider.hashPrefix()); // Configure the routes routesManagerProvider.configRoutes(""); });
<?php $useHtml5Mode = true; include("../common.php"); ?>
angular.module("html5Module", ["mainModule"]) .config(function ($locationProvider, startupInfoProvider, routesManagerProvider) { $locationProvider.html5Mode(true).hashPrefix("!"); // Set the current URLs configuration in the startupInfoProvider // so we can have it also outside the configuration phase. startupInfoProvider.setURLsConfig($locationProvider.html5Mode(), $locationProvider.hashPrefix()); var baseRouteURL = startupInfoProvider.$get().getBaseURL() + "/html5"; // Configure the routes routesManagerProvider.configRoutes(baseRouteURL); });
<IfModule mod_rewrite.c> RewriteEngine On RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule theviews/(.*)$ /code/examples/routing/02_RouteService/example/html5/index.php [NC,L] </IfModule>
<div style="background-color: #fcfcfc; border: 1px solid #e1e1e1; text-align: center; width: 200px;"> Default view </div>
<div style="background-color: #fcfcfc; border: 1px solid #e1e1e1; padding: 6px; width: 300px;"> View 1<br /> Controller name: {{controllerName}} </div>
<div style="background-color: #fcfcfc; border: 1px solid #e1e1e1; text-align: center; width: 200px;"> View 2 </div>
<div style="background-color: #fcfcfc; border: 1px solid #e1e1e1; padding: 6px; width: 350px;"> View 3<br /> - param1: {{view3.param1}}<br /> - param2: {{view3.param2}} </div>
<div style="background-color: #fcfcfc; border: 1px solid #e1e1e1; padding: 6px; width: 250px;"> View 4<br /> - param1: {{view4.param1}}<br /> - param2: {{view4.param2}} </div>
<div style="background-color: #fcfcfc; border: 1px solid #e1e1e1; padding: 6px; width: 350px;"> View 8<br /> Controller name: {{controllerName}}<br /> - param1: {{param1Value}}<br /> - param2: {{param2Value}} </div>
<div style="background-color: #fcfcfc; border: 1px solid #e1e1e1; padding: 6px; width: 350px;"> View 9<br /> Controller name: {{controllerName}}<br /> - param1: {{param1Value}}<br /> - param2: {{param2Value}} </div>
<div style="background-color: #fcfcfc; border: 1px solid #e1e1e1; padding: 6px; width: 450px;"> View 10<br /> Controller name (in main scope): {{controllerName}}<br /> Controller name (in scope alias): {{ctrlAlias.controllerName}}<br /> - param1: {{ctrlAlias.param1Value}}<br /> - param2: {{ctrlAlias.param2Value}} </div>
<div style="background-color: #fcfcfc; border: 1px solid #e1e1e1; padding: 6px; width: 600px;"> View 11<br /> Controller name: {{controllerName}}<br /> - delayTime: {{delayTime}}<br /> - routingDelay result: {{routingDelayResult}}<br /> - customFunction result: {{customFunctionResult}} </div>

Example


Description


In this example we're going to take a look at the $route service. This service allows you to map different URLs to different views and react whenever there's a match between a URL and a defined route. To work with the $route service, we need the ngRoute module which can be found in the angular-route.js file.

This example works both in hashbang and HTML5 mode. I recommend you to download the full source code of the example through the link under the source code boxes because there are many files and it will be easier to follow the description with all the files clearly visible in your favorite editor. The structure of the files shows that there are common files used by both modes (common.php and script.js in the root of the example) and two directories, hashbang and html5, to initialize the web application in one of the two modes. There's also the html5/.htaccess file to redirect all the HTML5 mode URL requests to the entry point of the HTML5 mode application, html5/index.php (you can find more information about this in the $location service example). Inside the script.js file in the root of the example we have a couple of providers: startupInfo and routesManager. The first one is useful to store a few initialization parameters at the application startup while the second one is useful to configure all the routes (with the configRoutes method). common.php is in fact our main HTML page. Here you can see that all the links are defined with the ng-href directive instead of just using href. The reason for this is that we use data binding ({{}}) in the URLs and to make AngularJS write the URLs correctly we must use the ng-href directive (see the official AngularJS documentation about the ng-href directive). In the root of the example, you see also the views directory. It contains almost all the views used by the routes defined in the example (some views are defined inline so they don't need an external file).

Now we can move on and see what each defined route does. A route is defined through the when(path, route) method of the $route provider that accepts two parameters: a path string and a route object. Whenever the specified path is matched (the path is matched against $location.path), the route object is used to display a specific view. Every time a new view is loaded by the $route service, it goes inside the HTML tag that contains the ng-view directive. You can see it in the common.php file. Here are the different routes in the example (mappings between route paths and route objects).

  1. Simple route with a template URL
    This maps the /theviews/viewone path to the following route object:
    {
      templateUrl: startupInfoProvider.$get().getBaseURL() + "/views/view1.html"
    }
        
    Here templateUrl is a simple string containing the URL of the view that has to be displayed. The controller used for the loaded view is the same one used for the HTML tag that contains the ng-view directive.

  2. Simple route with a template URL returned by a function
    This maps the /theviews/viewtwo path to the following route object:
    {
      templateUrl: function ()
      {
        return startupInfoProvider.$get().getBaseURL() + "/views/view2.html";
      }
    }
        
    Here templateUrl is a function that returns the string containing the URL of the view that has to be displayed.

  3. Route with multiple parameters
    This maps the /theviews/viewthree/:param1/subview1/:param2*\/subview2/ path to the following route object:
    {
      templateUrl: function (params)
      {
        routesOutputScope.view3 = {
          param1: params.param1,
          param2: params.param2
        };
    
        return startupInfoProvider.$get().getBaseURL() + "/views/view3.html";
      }
    }
        
    Here templateUrl is a function that returns the string containing the URL of the view that has to be displayed. The path defines some parameters that are available in the params argument of the templateUrl function. :param1 in the path defines a parameter named param1. This parameter cannot contain slashes. The syntax :param2*\ matches instead all the content between the .../subview1/ and the /subview2/ parts including any slashes if present and everything is made available to us through the parameter named param2. Both the parameters defined in the path are mandatory for the route to be matched.

  4. Route with optional parameters
    This maps the /theviews/viewfour/:param1?/:param2? path to the following route object:
    {
      templateUrl: function (params)
      {
        routesOutputScope.view4 = {
          param1: params.param1,
          param2: params.param2
        };
    
        return startupInfoProvider.$get().getBaseURL() + "/views/view4.html";
      }
    }
        
    Here templateUrl is a function that returns the string containing the URL of the view that has to be displayed. The path defines some parameters that are available in the params argument of the templateUrl function. :param1? and :param2? in the path define two optional parameters named param1 and param2 respectively. Since both the parameters defined in the path are optional, the route is matched for URLs like /theviews/viewfour, /theviews/viewfour/value1 and /theviews/viewfour/value1/value2.

  5. Simple route with an inline template
    This maps the /theviews/viewfive path to the following route object:
    {
      template: "<div style=\"background-color: #fcfcfc; border: 1px solid #e1e1e1; text-align: center; width: 200px;\">View 5</div>"
    }
        
    Here template is a string that contains the HTML of the view that has to be displayed.

  6. Route with parameters and with an inline template returned by a function
    This maps the /theviews/viewsix/:param1/:param2? path to the following route object:
    {
      template: function (params)
      {
        routesOutputScope.view6 = {
          param1: params.param1,
          param2: params.param2
        };
    
        return "<div style=\"background-color: #fcfcfc; border: 1px solid #e1e1e1; padding: 6px; width: 250px;\">" +
            "View 6<br />" +
            "- param1: {{view6.param1}}<br />" +
            "- param2: {{view6.param2}}" +
          "</div>";
      }
    }
        
    Here template is a function that returns the HTML of the view that has to be displayed. The path defines some parameters that are available in the params argument of the template function. :param1 in the path defines a mandatory parameter named param1 while :param2? defines an optional parameter named param2. The route is matched for URLs like /theviews/viewsix/value1 and /theviews/viewsix/value1/value2.

  7. Redirect to another route (and add two parameters)
    This maps the /theviews/viewseven/:param1 path to the following route object:
    {
      redirectTo: function (params, path, searchParams)
      {
        return baseRouteURL + "/theviews/viewfour/" + params.param1 + "/" + searchParams.searchParam1;
      }
    }
        
    Here redirectTo is a function that returns the URL of a different route (redirection). The path defines one mandatory parameter named param1 that is available in the params argument of the redirectTo function. In the same function also the path (path) and the search parameters (searchParams) of the URL are available. The route is matched for URLs like /theviews/viewseven/value1 and extracts the search parameters in URLs like /theviews/viewseven/value1?searchParam1=value2.

  8. Use a different controller for the view
    This maps the /theviews/vieweight/:param1/:param2 path to the following route object:
    {
      templateUrl: startupInfoProvider.$get().getBaseURL() + "/views/view8.html",
      controller: "additionalController1"
    }
        
    Here templateUrl is a simple string containing the URL of the view that has to be displayed. The path defines two mandatory parameters named param1 and param2. The controller named additionalController1 (with its own scope) is associated to the view. Inside the controller, we can get the values of the two parameters in the path by using the $routeParams service. The route is matched for URLs like /theviews/vieweight/value1/value2.

  9. Use a different controller for the view (controller defined inline)
    This maps the /theviews/viewnine/:param1/:param2 path to the following route object:
    {
      templateUrl: startupInfoProvider.$get().getBaseURL() + "/views/view9.html",
      controller: function ($scope, $routeParams)
      {
        // Store the name of the controller in a variable of the scope
        $scope.controllerName = "additionalController2";
    
        $scope.param1Value = $routeParams.param1;
        $scope.param2Value = $routeParams.param2;
      }
    }
        
    Here templateUrl is a simple string containing the URL of the view that has to be displayed. The path defines two mandatory parameters named param1 and param2. A new controller is defined inline and is associated (with its own scope) to the view. Inside the controller, we can get the values of the two parameters in the path by using the $routeParams service. The route is matched for URLs like /theviews/viewnine/value1/value2.

  10. Use a different controller for the view and define an alias for it
    This maps the /theviews/viewten/:param1/:param2 path to the following route object:
    {
      templateUrl: startupInfoProvider.$get().getBaseURL() + "/views/view10.html",
      controller: "additionalController3",
      controllerAs: "ctrlAlias"
    }
        
    Here templateUrl is a simple string containing the URL of the view that has to be displayed. The path defines two mandatory parameters named param1 and param2. The controller named additionalController3 (with its own scope) is associated to the view. Inside the controller, we can get the values of the two parameters in the path by using the $routeParams service. In this route object we define also an alias for the controller (ctrlAlias) and this means that we can get the scope of the controller directly with the this object inside the controller's function, and we can interact with the same scope by using the ctrlAlias name inside the view. In this way, inside the view we still have access to the scope of the parent controller in case we don't explicitly specify the alias for the new controller. The route is matched for URLs like /theviews/viewten/value1/value2.

  11. Resolve (wait for all the promises to be resolved)
    This maps the /theviews/vieweleven/:delayTime path to the following route object:
    {
      templateUrl: startupInfoProvider.$get().getBaseURL() + "/views/view11.html",
      controller: "additionalController4",
      resolve: {
        // Parametric delay (function that returns a promise)
        routingDelay: function($route, $q, $timeout)
        {
          // Get the delay time from the "delayTime" parameter of the route.
          //
          // NOTE: $routeParams cannot be used here because it
          //       still refers to the previous route and will
          //       change only when all the dependencies of the
          //       current route will be resolved; $route.current.params
          //       can be used instead.
          var delayTime = $route.current.params.delayTime;
    
          var deferred = $q.defer();
    
          // Generate a delay
          $timeout(
            function ()
            {
              deferred.resolve("routingDelay function waited for " + delayTime + " milliseconds");
            },
            delayTime);
    
          // Return the promise and the new controller "additionalController4"
          // will be instantiated only when all the promises defined
          // inside "resolve" will be resolved (in this example, the promise
          // returned by the "routingDelay" function is the only one, so
          // the new controller "additionalController4" will be
          // instantiated as soon as this promise is resolved).
          return deferred.promise;
        },
        // "routeParamsAlias" is just an alias for the "$routeParams" service and
        // will be injected in the controller of this route ("additionalController4").
        routeParamsAlias: "$routeParams",
        // "customFunction"'s result will be injected in the controller
        // of this route ("additionalController4").
        customFunction: function ()
        {
          return "result from customFunction";
        }
      }
    }
        
    Here templateUrl is a simple string containing the URL of the view that has to be displayed. The path defines one mandatory parameter named delayTime. The controller named additionalController4 (with its own scope) is associated to the view. In the resolve object we define three different things: the routingDelay function that returns a promise, the routeParamsAlias field that contains a string and the customFunction function that returns a string. If the resolve object contains some functions that return promises (just routingDelay in this case), then the new controller is instantiated only after all the promises are resolved or any of them is rejected. The value of the resolved promises can be injected in the route's controller. If the resolve object contains a field that represents a string, then the name of the field is just an alias for the service specified in the string (here the routeParamsAlias field is an alias for the $routeParams service). If the resolve object contains a field that represents a function (like customFunction), then the result of the function is injected in the route's controller. In general, all the fields defined in the resolve object can be injected in the route's controller just by specifying the field names among the arguments of the the controller's definition function. The route is matched for URLs like /theviews/vieweleven/value1.

  12. Invalid view (redirect to the default route and display the default view)
    In case none of the previously defined routes matches, then we can specify a default redirection by using the otherwise(route) method with the following route object:
    {
      redirectTo: baseRouteURL + "/theviews/defaultview"
    }
        
    Here redirectTo returns the URL of the default route (redirection). The path of default route (/theviews/defaultview) is mapped to the following route object where we just specify the URL of the default view:
    {
      templateUrl: function ()
      {
        return startupInfoProvider.$get().getBaseURL() + "/views/defaultview.html";
      }
    }