AngularAMD + ui-router + nombre del controlador dynamic?

Intento escribir una ruta general en mi aplicación y resolver la vista y los nombres de los controladores sobre la marcha en función de los parámetros de la ruta.

Tengo el siguiente código que funciona:

$stateProvider.state('default', angularAMD.route({ url: '/:module/:action?id', templateUrl: function (params) { var module = params.module; var action = module + params.action.charAt(0).toUpperCase() + params.action.substr(1); return 'app/views/' + module + '/' + action + 'View.html'; }, controller: 'userController', })); 

Sin embargo, no puedo encontrar una manera de resolver dinámicamente el nombre del controlador. Intenté usar resolve como se describe aquí , pero el enrutador ui parece manejar la resolución de forma diferente que la ruta angular.

¿Alguna sugerencia?

EDITAR : Ya he intentado usar controllerProvider pero no funciona para mí (por ejemplo, el siguiente código simplemente devuelve un nombre de controlador codificado para probar si realmente funciona):

 controllerProvider: function () { return 'userController'; } 

Me da el siguiente error:

Error: [ng: areq] Argumento ‘userController’ no es una función, no está definido http://errors.angularjs.org/1.3.3/ng/areq?p0=userController&p1=not%20aNaNunction%2C%20got%20undefined

Este es un enlace al trabajo plunker .

solución

Necesitamos dos características del UI-Router:

  • resolver (cargar las piezas faltantes del código js)
  • controllerProvider (ver citas de la documentación a continuación)

angularAMD – main.js definición

Este sería nuestro main.js, que contiene la conversión inteligente controllerName – controllerPath:

 require.config({ //baseUrl: "js/scripts", baseUrl: "", // alias libraries paths paths: { "angular": "angular", "ui-router": "angular-ui-router", "angularAMD": "angularAMD", "DefaultCtrl": "Controller_Default", "OtherCtrl": "Controller_Other", }, shim: { "angularAMD": ["angular"], "ui-router": ["angular"], }, deps: ['app'] }); 

Controladores:

 // Controller_Default.js define(['app'], function (app) { app.controller('DefaultCtrl', function ($scope) { $scope.title = "from default"; }); }); // Controller_Other.js define(['app'], function (app) { app.controller('OtherCtrl', function ($scope) { $scope.title = "from other"; }); }); 

app.js

En primer lugar, necesitaríamos algún método para convertir el param (por ejemplo, id) en el nombre del controlador. Para nuestros propósitos de prueba, usemos esta implementación ingenua:

 var controllerNameByParams = function($stateParams) { // naive example of dynamic controller name mining // from incoming state params var controller = "OtherCtrl"; if ($stateParams.id === 1) { controller = "DefaultCtrl"; } return controller; } 

.state()

Y esa sería finalmente nuestra definición de estado

 $stateProvider .state("default", angularAMD.route({ url: "/{id:int}", templateProvider: function($stateParams) { if ($stateParams.id === 1) { return "
ONE - Hallo {{title}}
"; } return "
TWO - Hallo {{title}}
"; }, resolve: { loadController: ['$q', '$stateParams', function ($q, $stateParams) { // get the controller name === here as a path to Controller_Name.js // which is set in main.js path {} var controllerName = controllerNameByParams($stateParams); var deferred = $q.defer(); require([controllerName], function () { deferred.resolve(); }); return deferred.promise; }] }, controllerProvider: function ($stateParams) { // get the controller name === here as a dynamic controller Name var controllerName = controllerNameByParams($stateParams); return controllerName; }, }));

Verifíquelo aquí, en este ejemplo de trabajo

documentación

Como se documenta aquí: $ stateProvider , para un state(name, stateConfig) podemos usar controller y controllerProvider . Algunos extractos de la documentación:

controllerProvider

controller (opcional) stringfunction

Controlador fn que debe asociarse con el scope recién relacionado o el nombre de un controlador registrado si se pasa como una cadena. Opcionalmente, los ControllerAs se pueden declarar aquí.

 controller: "MyRegisteredController" controller: "MyRegisteredController as fooCtrl"} controller: function($scope, MyService) { $scope.data = MyService.getData(); } 

controllerProvider (opcional)

Función de proveedor inyectable que devuelve el controlador o cadena real.

 controllerProvider: function(MyResolveData) { if (MyResolveData.foo) return "FooCtrl" else if (MyResolveData.bar) return "BarCtrl"; else return function($scope) { $scope.baz = "Qux"; } } 

resolver

resolve (opcional)

Un map opcional map de dependencias que debe ser inyectado en el controlador. Si alguna de estas dependencias es prometedora , el enrutador esperará a que TODAS se resuelvan antes de que se cree una instancia del controlador …

Es decir, use controllerProvider :

… para resolver dinámicamente el nombre del controlador …

En caso de que haya logrado llegar hasta aquí, tal vez le gustaría verificar otra solución similar con RequireJS – angular-ui-router con requirejs, carga lenta del controlador