Does AngularJS have dynamic routing?

Does angular support dynamic routing at all? Maybe some trick like this:

$routeProvider.when('/:ctrl/:action', 
                     getRoute($routeParams.ctrl,$routeParams.action))

function getRoute(ctrl, action){
   return {
      templateUrl: ctrl+"-"+action+".html"
      controller: 'myCtrl'
   }
}

Please help me, I need to get templateUrl based out of routeParams

This is a late answer but I came across this problem myself, but it turns out that the solution by Dan conflicts with ngAnimate classes on the ngView directive, and the view is shown but the ng-leave animation will immediately be applied and hide the view opened with his dynamic routing.

I found the perfect solution here, and it's available in 1.1.5 +

In the $routeProvider, the templateUrl value can be a function, and is passed the route parameters:

app.config(function ($routeProvider) {
$routeProvider
    .when('/:page', {
         templateUrl: function(routeParams){
             return '/partials/'+routeParams.page+'.html';
        }
    })
});

Though the controller can't be given as a function so my solution is to give it in the template html as per usual with ng-controller="HomeCtrl".

Using this solution we can route by convention in Angular. I hope this helps others who weren't keen on manually adding every route to the routeProvider.

You want to bring it down to the controller level.

In this example, I am overriding entire pages as well as partials by subdomain:

app.js

config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider) {
  $locationProvider.html5Mode(true);
  $routeProvider.when('/', {
    template: 'home'
  });
  $routeProvider.when('/contact', {
    template: 'contact'
  });
  $routeProvider.otherwise({redirectTo: '/'});
}])

controllers.js

controller('AppController', ['$scope','Views', function($scope, Views) {    
  $scope.$on("$routeChangeSuccess",function( $currentRoute, $previousRoute ){
    $scope.page = Views.returnView();
  });

  $scope.returnView = function(partial){
    return Views.returnView(partial);
  }    

}])

services.js

factory('Views', function($location,$route,$routeParams,objExistsFilter) {  

  var viewsService = {};
  var views = {
    subdomain1:{
      'home':'/views/subdomain1/home.html'
    },
    subdomain2:{

    },
    'global.header':'/views/global.header.html',
    'global.footer':'/views/global.footer.html',
    'home':'/views/home.html',
    'home.carousel':'/views/home.carousel.html',
    'contact':'/views/contact.html',
  };

  viewsService.returnView = function(partial) {
    var y = (typeof partial === 'undefined')?$route.current.template:partial;
    var x = $location.host().split(".");
    return (x.length>2)?(objExistsFilter(views[x[0]][y]))?views[x[0]][y]:views[y]:views[y];
  };

  viewsService.returnViews = function() {
  return views;
  };

  return viewsService;
}).

filters.js

filter('objExists', function () {
  return function (property) {
    try {
      return property;
    } catch (err) {
      return null
    }
  };
});

index.html

<!doctype html>
<html lang="en" ng-controller="AppController">
<body>
<ng-include src="returnView('global.header')"></ng-include>
<ng-include src="page"></ng-include>
<ng-include src="returnView('global.footer')"></ng-include>
</body>
</html>