Saltar al contenido

AngularJS – Controladores: El completo cómo

Cuando los controladores hacen el trabajo de preparar el modelo para la vista, o manejan las interacciones de la vista, lo más frecuente es que trabajen con servicios para hacer el trabajo real. Uno de los principales objetivos de diseño de AngularJS es utilizar la inyección de dependencia para eliminar la necesidad de la creación directa de estos servicios. Esto no sólo facilita los controladores de prueba de la unidad (como mostraré en breve), sino que también simplifica el código y hace más fácil su mantenimiento. Hay varias maneras diferentes de gestionar tanto la declaración como la resolución de las dependencias para un controlador.

El modelo primario para trabajar con las dependencias es pasar una matriz a la función constructora del controlador que enumera las dependencias por nombre e incluye una función a invocar que toma esas dependencias como parámetros, como en este ejemplo.

AngularJS – Controladores: El completo cómo
AngularJS – Controladores: El completo cómo
123456angular.module($0027hackApp$0027).controller($0027mentorControlador$0027,[$0027$http$0027,$0027$scope$0027,mentorControlador]);function mentorControlador($http, $scope){ $scope.mentors =[$0027Matt$0027,$0027Bob$0027,$0027Alice$0027,$0027Raj$0027,$0027Priscilla$0027];}

java

Obsérvese en este ejemplo que la función de controlador toma el nombre del controlador seguido de una matriz que incluye una lista de dependencias y la función de controlador. Obsérvese también que el orden de las dependencias es el mismo en la declaración y en la lista de parámetros. Obsérvese que también es posible excluir la matriz que enumera las dependencias y hacer que se deduzcan de los nombres de los parámetros de la función de controlador. Esto supone que los nombres de los parámetros coinciden con los nombres de los servicios y también hace que su código no sea seguro para la minificación, por lo que generalmente no es un enfoque recomendado.

Otro enfoque aplica la lista de dependencias a la función de controlador mediante una propiedad que proporciona otra opción segura de minificación. Esta opción es la preferida por muchos promotores ya que hace que la propia función del controlador sea más limpia y fácil de leer, especialmente cuando la lista de dependencias se hace más grande.

1234567angular.module($0027hackApp$0027).controller($0027technologyController$0027, technologyController);technologyController.$inject =[$0027$http$0027,$0027$scope$0027,$0027$routeParams$0027];function technologyController($http, $scope, $routeParams){//implementación omitida}

java

En este ejemplo la tecnologíaControlador es declarada como una función de controlador sin listar las dependencias. Entonces la propiedad $inject se establece en la función que lista esas dependencias. Al igual que en el método anterior, la lista de dependencias debe estar en el mismo orden que la lista de parámetros, por lo que tendrá que mantenerlas sincronizadas si añade, elimina o reordena los parámetros.

Debido a que ambos métodos enumeran las dependencias como cadenas, los valores no serán minados cuando su código se procese para la minificación. Esto significa más trabajo al listar las dependencias dos veces y mantener la lista en sincronía. Debido a esto, un proyecto de código abierto, ng-annotate, fue creado para simplificar este proceso permitiéndote simplemente definir los parámetros de la función y hacer que una herramienta de pre-procesamiento cree la propiedad $inject por ti en el controlador. Esta herramienta requiere que añadas un comentario o atributo a las funciones del controlador, pero que sea un marcador consistente que no esté vinculado a la lista de parámetros. Cuando empieces a construir aplicaciones, vale la pena echar un vistazo a ng-annotate y trabajarlo en tu cadena de herramientas para simplificar el código JavaScript para tus controladores.

Al usar el enrutamiento, hay ciertos escenarios en los que puede querer proporcionar las dependencias a su controlador como promesas en lugar de tenerlas resueltas directamente por el inyector AngularJS. Por ejemplo, si usted tiene servicios que cargarán datos asincrónicamente, o si necesita tomar decisiones sobre si mostrar la vista, y por lo tanto invocar al controlador, basado en algunos parámetros de ruta o datos devueltos de una dependencia. En esos casos, el proveedor de la ruta tiene una propiedad de resolución que usted puede establecer y que le permite resolver las dependencias y crear promesas que se resuelven todas antes de pasar al controlador.

12345.when($0027/model$0027,{ templateUrl:$0027/views/model.html$0027, controller:$0027modelController$0027, controllerAs:$0027model$0027, resolve:{$0027modelService$0027:modelServiceWrapper}

java

En este bit de código de la configuración del proveedor de la ruta, la dependencia llamada $0027modelService$0027 se resolverá con la función modelServiceWrapper que se muestra aquí.

1234función modeloServiceWrapper(){//reemplazar este pseudocódigo con una solicitud asincrónica al servidor de retorno{techs:[$0027JavaScript$0027,$0027ASP.NET$0027,$0027AngularJS$0027]};}

java

En este ejemplo he utilizado un código de prueba simple en el que normalmente se pondría la lógica de servicio para cargar elementos del servidor o resolver otros datos necesarios para el controlador. La función del controlador puede entonces declarar una dependencia en el modelService y utilizar el objeto resultante en su lógica de configuración ahora con la promesa resuelta, lo que significa que los datos ya han sido cargados.

123456789angular.module($0027hackApp$0027).controller($0027modelController$0027,[$0027modelService$0027, modelController]);function modelController(modelService){var vm =this; vm.techs = modelService.techs;}

java

El beneficio de este enfoque es que todas las promesas que necesita el controlador se resuelven antes de que el controlador necesite el resultado. Esto permite la toma de decisiones en el enrutamiento para cancelar las rutas o aplicar otra lógica basada en el contexto y los resultados de la promesa.