Al igual que ocurre en cualquier lenguaje de programación y con cualquier framework del tipo MV*, nunca deberías tener tu lógica de negocio en un controlador, sino inyectar a este servicios que te provean de esta.

 

Otra de las cosas que tienes que tener en cuenta es la separación de cada clase/function de JavaScript en un archivo distinto y después tener una buena estrategia de despliegue con herramientas como Grunt o Gulp, esta última es la que actualmente está utilizando el equipo de Angularjs.

 

Una vez aclarado este punto, vamos a partir en este capítulo de un ejemplo mal realizado y su posterior corrección, para ello os planteo un  simple módulo con un controlador y una llamada $http para recuperar una lista de valores desde un archivo json en el servidor.

 

Estructura del proyecto

image07

app.js

 

image00

Función responsable de la definición del módulo.

 

frameworks.json

image03

 

Archivo json estático con los datos que queremos recuperar y mostrar en nuestra vista.

 

myController.js

image05

En este controlador podemos observar que estamos recuperando los datos del archivo framework.json y asignandolos al objeto model de nuestro scope y es este el punto donde realmente está mal y que vamos a describir una vez hagamos una distribución correcta de nuestro código.

 

index.html

image01

En la vista simplemente lo que hacemos es declarar nuestras intenciones de utilización y binding así como cargar cada uno de los archivos JavaScript necesarios para el buen funcionamiento de esta.

 

Te has planteado, que ocurre si tengo 1000 vistas y mil controladores, crees que puede ser una buena idea cargar los 1000 controladores en archivos separados, es por eso por lo que planteaba el uso de herramientas con Grunt o Gulp.

Sample Gruntfile

http://travismaynard.com/writing/getting-started-with-gulp

 

Aparte de estos link para que vayas aprendiendo Gulp o Grunt te recomiendo las siguientes guías de estructura de una app Angularjs y que en nuestro ejemplo no estamos cumpliendo, puesto que solo nos queremos centrar en la separación de responsabilidades de nuestro controlador.

 

Angular Style Guide(Jhon Papa)

Angular Seed

Angular Style Guide(gocardless)

 

Piensa que ninguna de ellas es una doctrina y tu deberías de pensar que es lo más apropiado en cada una de tus app’s.

 

Hemos visto un mal ejemplo de un controlador por acceder a datos desde este, cuando su verdadera responsabilidad no es otra que controlar la lógica de la vista y por tanto el acceso a datos debería de estar en un servicio, tal y como se muestra a continuación.

 

FrameworkService.

image04

Controller.

image06

Centrándonos en el ejemplo correcto. Lo primero observa que ya no inyectamos en el controlador el ServiceProvider $http sino nuestro servicio frameworkService, que no hace otra cosa que recuperar el contenido del archivo framework.json y devolver una promise que enlazamos directamente a la vista por medio del objeto model.

 

Ojo con este tema puesto que a partir de versión 1.2.0+ de Angularjs, hay que especificar en configuración que queremos hacer esto, puesto que de serie ya no trabaja correctamente.

 

Para ello os mostramos que hay que hacer dentro de la configuración de vuestros módulos.

image02

Es decir invocamos la función unwrapPromises de $parseProvider con valor a true, os pasamos unos link para que amplies información acerca de esto y por tanto dejes de utilizarlo.

 

Why no promise AngularJS 1.2.0+

Migrating from 1.2 to 1.3

fix($parse): remove deprecated promise unwrapping

 

Con esto puedes llegar a la conclusión de implementar todas tus llamadas a servidor de esta forma, te aconsejamos que mires los siguientes módulos de Angularjs antes de hacer tu propio módulo.

ngResource

Restangular

O bien te invitamos a que pruebes nuestro módulo mgCrud desde el cual puedes resolver el acceso a datos REST de forma declarativa.

 

Bueno, visto una pequeña guía de buenas prácticas en Angularjs, vamos a pasar a desvelar qué objetos son los que nos proporciona Angularjs para escribir nuestra lógica de negocio.

 

Values.

 

Nos permite almacenar valores/objetos en nuestro módulo que después pueden ser inyectables dentro de servicios, factorías, providers, directivas y controladores.

 

myModule.value(“valor”,1);

myModule.value(“user”, {id:1,name:”@_pedrohurtado y @xavipaper”});

 

Constant.

 

Son lo mismo que values, pero con la particularidad que se pueden inyectar en el momento de la configuración del módulo para ser utilizadas por este, cosa que no podemos hacer con values.

 

Factory.

 

Nos devuelve un value o bien la instancia de un objeto o la invocación a una función, este tipo de objetos se invocan desde el inyector por invocación no por la creación de un nuevo objeto, aunque perfectamente podrías devolver un servicio invocando a new.

 

myModule.service(‘service’,function(){

      this.helloWord(){

           console.log(“Hello World”);

      };

});

 

myModule.Factory(‘factory’,function(service){

     return new service();

});

 

Observa la diferencia entre factory y service como puedes adivinar una factory dada la función de javascript fx(){}; Se invoca de la siguiente forma fx(), de forma que el ámbito de this no es la propia función, mientras que en un servicio la invocación sería de la siguiente forma new fx().

 

Service.

Se invoca a través del patrón Constructor injector.

 

Provider.

Al igual que los servicios son invocados mediante el constructor. Pero con una pequeña diferencia que estos pueden ser inyectables al igual que las constantes en el config de nuestro módulo y que obligatoriamente tienen que exponer una función llamada $get que es la función inyectable.

 

myModule.provider(‘framework’,function(){

            var _path;

            this.setPatch(path){

                _path = path;

            };

            this.$get = function($http){

                 function getAll(){

                        return $http.get(_path);

                 };

                  return getAll();

            };

});

 

Para utilizarlo lo que tendrías que hacer es configurarlo en el config inyectandolo con el nombre de tu servicio+Provider, en nuestro caso frameworkProvider, con lo cual lo que haremos será establecer el path mediante la función setPatch en nuestro config.

 

myModule.config(function(frameworkProvider){

     frameworkProvider.setPath(‘framework.js’);

});

 

Después lo puedes utilizar en un servicio, factoria, controlador o directiva pero inyectandolo sin la palabra Provider, es decir como framework, teniendo acceso de esta forma sólo a la función getAll() que retornas en this.$get.

 

Os pasamos unos link bastante interesantes donde se puede ver la diferencia de cada uno de estos objetos.

Providers

Service vs provider vs factory

 

Todos los objetos en Angular son Singleton, por ahorro lógicamente de consumo de memoria, aunque si lo necesitas puedes desde una factoría devolver una función y crearla con new desde un controlador o desde una directiva, nosotros no lo hemos hecho y nos hemos acostumbrado a trabajar con Singleton y por tanto es lo que te recomendamos.

 

Por último nos queda por citar los interceptors y los decorators en Angularjs, pero simplemente lo que vamos a hacer es pasar una referencia a la documentación oficial, puesto que es bastante buena, así como ver la posibilidad de decorar una directiva.

 

Interceptors

$providers

Hacking Core Directives in AngularJS

 

@_PedroHurtado y @XaviPaper

Vínculo hacia el capítulo anterior: (8) Forms

Tags: , , ,
Ingeniero Informático por la Universidad Politécnica de Valencia, Xavier Jorge (@XaviPaper) trabaja como CTO de Ami2 y lleva más de 13 años vinculado a proyectos de I+D+i con diversas universidades, y desarrollando y arquitecturando soluciones con tecnologías .Net.

Related Article

2 Comments

Juan Carlos Feb 13, 2015 at 16:07

Hola, buen día.

Estuve chequeando la información sobre el mgcrud, me agradaría que puedan realizar algunos ejemplos con base de datos.

Saludos.

    Xavier Jorge Cerdá Feb 14, 2015 at 17:18

    Buenas tardes,

    Realmente mgCrud es un framework que obtiene y hace peticiones a una interface ApiRest. Ya detrás de esta API se encuentra la BD que se accederá desde esa parte servidora. mgCrud no está pensado para acceder directamente a la BD sino a través de un API que es donde realizará las peticiones que consideres oportunas GET, POST, PUT, DELETE, …

    Espero haberme explicado.

    Saludos

Leave a Comment

Uso de cookies

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies, pinche el enlace para mayor información.plugin cookies

ACEPTAR
Aviso de cookies