简体   繁体   中英

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?

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!

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.

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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM