web-dev-qa-db-fra.com

chargement dynamique du contrôleur dans angularjs $ routeProvider

J'ai actuellement une application AngularJS avec routage intégré et elle fonctionne parfaitement avec les affectations de propriétés controller statiques. mais ce que je veux vraiment faire, c’est d’affecter dynamiquement des contrôleurs avec différentes routes:

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

Ce que je voudrais faire est de faire la même chose à propos de ma propriété controller ici, comme ceci:

$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)
           }
  })

mais comme il semble que je reçois une erreur en disant que paramsProvider est introuvable

alors est-il possible de charger dynamiquement le nom de ma fonction de contrôleur dans la configuration de la route?

21
Kia Panahi Rad

Ceci est possible en utilisant angular ui-router .

Le routeur ui vous permet de spécifier un "controllerProvider" pour spécifier une fonction permettant de fournir un contrôleur. Donc, la solution ressemblerait à ceci:

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

J'espère que ça aide!

11
Bradley Trager

J'ai résolu ce problème en ne spécifiant pas le contrôleur dans $ routeProvider, mais en le plaçant dans le fichier spécifié dans templateURL.

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

Dans DashboardsNAME.html

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

Cette technique nécessite toujours qu’à un moment donné avant l’instanciation de la route, vous ayez enregistré DashboardsNAMEController. Je suppose que le meilleur endroit pour le faire est dans la méthode module.run() avec appel vers votre propre service, mais je le fais dans mon contrôleur principal, car il fonctionne et est un contrôleur court de toute façon.

7
Nathaniel Johnson

J'ai essayé cette même chose. Une solution que j'ai trouvée consiste à le faire dans votre routeProvider:

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

Et ensuite, vous calculez pour quel "pseudo-contrôleur" (faute d'un meilleur nom) charger dans la définition de "dynamicController".

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);
}]);

Cela suppose que $ routeParams.dashboardName est l’un des ["uno", "dos"].

Prenez ceci avec un grain de sel car je n'ai eu que 3 jours avec Angular, mais jusqu'à présent, cette approche a très bien fonctionné pour ce que j'essaie d'accomplir.

4
Benjamin Oman

Je ne sais pas si cela dépend de la version d'AngularJS mais vous pouvez utiliser une fonction pour la propriété controller, la fonction devenant le contrôleur réel. En utilisant ce fait conjointement avec héritage du contrôleur , vous pouvez obtenir un code plus condensé comme celui que vous recherchiez, je pense:

$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});
    }
})

Avertissement: Honnêtement, je ne sais pas si cette approche présente des inconvénients. Ne semble pas si bien.

3
mettjus

Voici quelque chose qui fonctionne aussi (du moins pour moi). Cela peut aider les personnes futures à chercher une réponse. 

$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;
        },

Pas le code le plus court mais au moins plus facile à lire. De même, si vous souhaitez attribuer à controller un nom différent de l'onglet/nom de tableau de bord.

0
CENT1PEDE