dynamically loading the controller in angularjs $routeProvider
Asked Answered
L

5

20

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?

Lactoscope answered 24/8, 2013 at 20:58 Comment(0)
D
11

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!

Deadening answered 7/1, 2014 at 20:13 Comment(1)
ah, I reread the question and understand what was being asked (and removed my answer). Your solution will work to dynamically determine the controller's name, but the controller would still need to be fetched and loaded from the server dynamically which doesn't appear to be part of the question, but an FYI for future readers.Preoccupy
M
7

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.

Mansell answered 5/12, 2013 at 5:30 Comment(6)
This works, but I do not understand why the other way does not work.Deadening
@BradleyTrager Which other one?Mansell
The one in the question where the controller is specified in a function on the route provider.Deadening
He is linking a function that will act as a controller to the route. The routeParams are not available to that controller. If he wants the controller to be params.dashboardName+"Controller" he needs to turn that line into an expression like : controller: params.dashboardName+"Controller" and not wrap it in a function.Mansell
Thank you, I get it now! Now I am just wondering how to get the "params" without wrapping it in a function.Deadening
Take a look at @Benjamin Oman's answer on dynamic controllers. Also, this issue is the reason I submitted: github.com/angular/angular.js/issues/5410 Put a +1 in comments if you like it.Mansell
H
4

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.

Holozoic answered 8/10, 2013 at 8:28 Comment(0)
C
4

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.

Confessional answered 5/4, 2014 at 19:4 Comment(0)
A
0

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.

Arianna answered 12/8, 2015 at 16:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.