Mostrando las entradas con la etiqueta html5. Mostrar todas las entradas
Mostrando las entradas con la etiqueta html5. Mostrar todas las entradas

jueves, junio 05, 2014

AngularJS UI Router, resolve & Unknown service provider ERROR

La noche de ayer me quedé en la oficina terminando de corregir algunos aspectos de una aplicación. Una aplicación móvil híbrida con AngularJS, Angular UI Router y Bootstrap. El código estaba bien, pero uno de mis controladores estaba gatillando el error Unknown service provider.

Angular UI Router  permite conceptualizar una aplicación web como una máquina de estados.
Cada acción que se realiza puede ser un estado separado, y cada estado, desde el enfoque de desarrollo que estamos adoptando, tiene sus propias vistas.
A su vez, cada vista esta manejada por su propio controlador, y eventualmente antes de cargarse puede requerir que resuelva determinada petición (resolve).

Ejemplificando con código:

app.config(function ($stateProvider, $urlRouterProvider) {
    $urlRouterProvider
          .when('/', '/login')
          .otherwise('/');


    $stateProvider
        .state('login', {
            url: '/login'
            , views: {
                'login': {
                    templateUrl: 'include/login.include.html'
                    , controller: 'loginCtrl'
                }
            }
            , onEnter: function() {
                loggedin = false;
                localStorage.setItem('loggeduser', null);
            }
        })
        .state('plan', {
            url: '/plan'
            , views: {
                'menu': {
                    templateUrl: 'include/menu.include.html'
                    , controller: 'menuCtrl'
                } 

                , 'plan': {
                    templateUrl: 'include/plan.include.html'
                    , controller: 'planCtrl'

                }
                , 'client': {
                    templateUrl: 'include/client.include.html'
                    , controller: 'clientCtrl'
                    , resolve: {
                        clients: ['pouchWrapper', function(pouchWrapper){
                            var cliMap = function(doc){
                                if(doc.dbtable === 'cli'){
                                    emit(doc, null);
                                }
                            }

                            // Rescata el listado de clientes desde un repositorio local
                            return pouchWrapper.retrieveList(cliMap);
                        }]
                    }                  
                }            }           
            , onEnter: function($location) {              
                if(!loggedin){
                    console.log('No ha ingresado al sistema');                                       
                    $location.path('/logout');
                }
            }
        }) ;

});

Si se dan cuenta algunas plantillas (template) tienen indicado cual es su correspondiente controlador (controller).

Y en el controlador clientCtrl

app.controller('clientCtrl', ['$scope', '$location', 'clients', 
    function($scope, $location, clients){
        // ... aqui va mucho código
    }]);

El problema es que estando bien codificada la máquina de estados, y cargando cada vista como correspondía, AngularJS reportaba el error Unknown service provider para clients, sin indeicar origen del error ni líneas de referencia (es una maravilla depurar código a ciegas :-/ ).
Después de mucho buscar y leer en la Wiki y sección de Issues del Github de Angular UI Router, llegué a un post en StackOverflow (lo siento, perdí el enlace  original), donde explicaban que
el error se genera cuando el estado tiene el controlador referenciado tanto en la configuración como dentro de la plantilla.


En la plantilla include/client.include.html

<div data-ng-controller="clientCtrl">
    <!-- ... aquí va el contenido de la plantilla para el bloque client -->
</div>


El error lo he destacado en negrita, el controlador o está referenciado en la configuración del estado, o está referenciado dentro de la plantilla, pero NO en ambos.

Después de ver la solución, y corregir el problema (eliminando la referencia al  controlador en la plantilla) es entendible lo que está sucediendo. Si recuerdan, el controlador recibe como tercer parámetro clients (que es lo indicamos en el atributo resolve del estado, que queremos resolver antes de desplegar) . Al poner la referencia directamente en la plantilla, clients queda vacío, ergo Unknown service provider.




domingo, diciembre 15, 2013

¿Es el fin de las aplicaciones de escritorio?

Hace poco me encomendaron  el desarrollo de un sistema de software. Inicialmente pensé en usar Java, pero terminé con algo "más web".



Cuando nos enfrentamos al desarrollo de software, aparte del diseño acorde a la captura de requerimientos que se haya realizado, y las interfaces de usuario; entre muchas otras cosas; se debe escoger la tecnología adecuada.

La elección de que tecnología utilizar normalmente va ligada a la instalación, vale decir en las características de la máquina del cliente donde se instalará la aplicación. En la propuesta inicial pensé en realizar el desarrollo usando Java y una base de datos H2. Logré un avance para la generación medianamente rápida de la GUI, sin embargo me di cuenta que para conseguir interfaces de usuario sencillas, y por sobretodo intuitivas, Java me limitaba demasiado, aún considerando Swing, JavaFX y muchas otras librerías de terceros que entregan infinitas alternativas.



La alternativa:

Hacer un desarrollo "más web", vale decir desarrollar el FrontEnd en HTML y el backend en modo "servidor". Entre las elecciones "lógicas" estaba utilizar un servidor Apache Tomcat, un Jetty, o algo para contener JSP y Servlets, o usar Apache (o similar) con PHP.
El problema de esas opciones es que el computador huésped, la máquina del cliente y usuario final, de una u otra manera termina convirtiéndose en un servidor, eso sin considerar la cantidad de dependencias que se deben considerar:
  • JDK de Java
  • Servidor web
  • Motor de base de datos
  • Plugins varios
  • etc.

Pensé ¿.NET será una alternativa? y el problema es similar al de Java, necesitas previamente instalar muchas dependencias. Si el PC del cliente no tiene todo lo necesario, una aplicación que pesa un par de megas significa finalmente descargar sobre 40 MB de instaladores anexos. ¿Cómo evitamos eso?

De vuelta al enfoque inicial

¿Una WebApp local quizás? Con eso se soluciona el peso de la aplicación, aunque hay 2 problemas:
  1. El almacenamiento de datos usando WebDB está limitado a las restricciones del navegador que se utilice. Eso y los riesgos que el usuario utilice distintos navegadores, generando inconsistencias en la información, o que haga una limpieza agresiva del caché del navegador (lo que eliminaría la BD).
  2. La versión del navegador es un elemento que no se puede ignorar, y créanlo, aún hay usuarios de Internet Explorer 6...

Busqué alternativas disponibles, y ahorrándoles el proceso de análisis y selección de la a mi parecer mejor, finalmente llegué a node-webkit.
Aprovechando mi reciente incursión con Node.js decidí hacer algunas pruebas, que luego de resolver un par de problemas han resultado en una aplicación que cumple todas mis expectativas. Lo que utilicé:


Y una vez llegado a esto empiezo a cuestionar que tanto vale la pena desgastarse tratando de hacer una aplicación de escritorio, con miles de dependencias y limitaciones. Más considerando que hoy en día todo avanza hacia convertirse en Web:
  • La comunicación entre las personas se vuelve más y más Web, sólo piensen en las redes sociales.
  • La experiencia de juego cada vez se enlaza más a la Web.
  • Aplicaciones móviles desarrolladas de manera híbrida, vale decir HTML5+CSS3+JavaScript+API nativas. Phonegap lleva mucho avanzado en esta línea.
  • Las aplicaciones de Windows 8, que muchas veces están desarrolladas 100% usando tecnologías web.
  • Los temas de escritorio de GnomeShell utilizan CSS para muchas de sus definiciones.
  • Muchos widgets de escritorio de cada uno de los distintos sistemas operativos
  • El mismo Node.js que es JavaScript en el servidor.
  • Me arriesgaría a decir que más del 90% de los desarrollos de Google.

Incluso escalar este el modelo de aplicación de escritorio web no es tan difícil, pensando en un escenario en el que se decida masificar el uso de la aplicación en la organización.

Estoy claro que esta línea puede no ser la respuesta a todos los problemas que podemos enfrentar en desarrollo de software, pero al menos a mi me hace dar una segunda mirada cada vez que me hablan de desarrollar una aplicación de escritorio.

Si tienen dudas sobretodo respecto a como resolver la persistencia de datos con node-webkit, Sequelize y SQLite no duden en hacerlas.