Kia Raad
Kia Raad

Reputation: 1335

dynamically loading the controller in angularjs $routeProvider

I currently have an AngularJS app with routing built in and it works perfectly with static controller property assignments. but what I really want to do is to dynamically assign controllers with different routes:

$routeProvider
 .when("/Dashboards/:dashboardName",{
    templateUrl:function(params) {
                 return "Dashboards/" + params.dashboardName;
                //some ASP.NET MVC calls to return partial views (this part works)
        }
  })

What I would like to do is to do the same thing about my controller property here, like:

$routeProvider
 .when("/Dashboards/:dashboardName",{
       templateUrl:function(params) {
             return "Dashboards/" + params.dashboardName;
            //some ASP.NET MVC calls to return partial views (this part works)
           },
       controller: function(params) {
             return params.dashboardName+"Controller"; (this part DOESN'T work)
           }
  })

but as it seems I am get an error saying paramsProvider is not found

so is there any way I could dynamically load my controller function name in route configuration?

Upvotes: 20

Views: 18983

Answers (5)

Bradley Trager
Bradley Trager

Reputation: 3590

This is possible to do using angular ui-router.

The ui-router lets you specify a "controllerProvider" to specify a function for providing a controller. So the solution would look like this:

$stateProvider
.state("/Dashboards/:dashboardName",{
   templateUrl:function($stateParams) {
         return "Dashboards/" + $stateParams.dashboardName;
       },
   controllerProvider: function($stateParams) {
         return $stateParams.dashboardName+"Controller";
       }
  })

I hope it helps!

Upvotes: 11

jofftiquez
jofftiquez

Reputation: 7708

Here is something that also works, (at least for me). This may help future people searching for answer.

$stateProvider
    .state('foo', {
        url: '/foo/:bar',
        templateUrl: 'some-template-path.html',
        resolve : {
            getController : function($stateParams){
                if ($stateParams.bar === "tab1") {

                    return "tab1Controller"

                }else if ($stateParams.bar === "tab2") {

                    return "tab2Controller"

                }else if ($stateParams.bar === "tab3"){

                    return "tab3Controller"

                }else if ($stateParams.bar === "tab4") {

                    return "tab4Controller"

                }
            }
        },
        controllerProvider: function(getController){
            return getController;
        },

Not the shortest code but at least easier to read. Also if you want to give the controller a different name from the tab/dashboardName name.

Upvotes: 0

mettjus
mettjus

Reputation: 2988

I don't know if it depends on AngularJS version but you can serve a function to the controller property, the function becoming the actual controller. Using this fact in conjunction with controller inheritance you can obtain a more condensed code like the one you were looking for, I think:

$routeProvider
.when("/Dashboards/:dashboardName",{
    templateUrl:function(params) {
        return "Dashboards/" + params.dashboardName;
    },
    controller: function($scope, $routeParams, $controller) {
        /* this creates a child controller which, 
           if served as it is, should accomplish 
           your goal behaving as the actual controller
           (params.dashboardName + "Controller") */
        $controller($routeParams.dashboardName + "Controller", {$scope:$scope});
    }
})

Disclaimer: I honestly don't know if this approach has any drawbacks. Doesn't look so though.

Upvotes: 4

Nathaniel Johnson
Nathaniel Johnson

Reputation: 4839

I solved this issue by not specifying the controller in $routeProvider but instead placing it in the file specified in templateURL.

$routeProvider
 .when("/Dashboards/:dashboardName",{
    templateUrl:function(params) {
                 return "Dashboards/" + params.dashboardName;
        }
  })

In DashboardsNAME.html

<div class="container" ng-Controller='DashboardsNAMEController'>Food</div>

This technique still requires that at some point before the route is instantiated you have registered DashboardsNAMEController. I suspect that the best place to do it is in the module.run() method with call to your own service but I do it in my main controller because it works and is a short controller anyway.

Upvotes: 7

Benjamin Oman
Benjamin Oman

Reputation: 1654

I have been attempting this same thing. One solution I've found is to do this inside your routeProvider:

 $routeProvider
    .when("/Dashboards/:dashboardName",{
        templateUrl:function(params) {
            return "Dashboards/" + params.dashboardName;
        },
        controller: 'dynamicController'
 });

And then you do your calculation for what "pseudo-controller" (for lack of a better name) to load inside of the "dynamicController" definition.

var controllers = {
    unoController: function($scope, $routeParams, $rootScope) {
        // Do whatever
    },
    dosController: function($scope, $routeParams, $rootScope) {
        // Whatever for this controller
    }
}

app.controller('dynamicController', ['$scope', '$routeParams', '$rootScope', function($scope, $routeParams, $rootScope) {
    controllers[$routeParams.dashboardName+"Controller"]($scope, $routeParams, $rootScope);
}]);

This assumes that $routeParams.dashboardName is one of ["uno","dos"].

Take this with a grain of salt as I've only had about 3 days with Angular, but so far this approach has worked great for what I'm trying to accomplish.

Upvotes: 4

Related Questions