1 CONFIDENTIAL©2013 GlobalLogic Inc. Introducción a AngularJS
2 ©2013 GlobalLogic Inc.CONFIDENTIAL
3 ©2013 GlobalLogic Inc.CONFIDENTIAL Conceptos Básicos Estructura de una aplicación Módulos Scopes Data-binding Servicios Directivas 01 02 03 04 05 06 07
4 ©2013 GlobalLogic Inc.CONFIDENTIAL Routing Filtros Forms Unit Testing 08 09 10 11
5 5CONFIDENTIAL Conceptos Básicos
6 6CONFIDENTIAL Que es AngularJs? Donde debería usarlo? Client-Side Templates MVC Data Binding Inyección de dependencias Directivas 01 02 03 04 05 06 07
7 7CONFIDENTIAL El código del curso esta en https://github.com/gastonadrian/CursoAngular.https://github.com/gastonadrian/CursoAngular AngularJs es un framework MV* diseñado para extender las capacidades de html. La idea principal detrás del diseño de AngularJs es proveer a los desarrolladores de un conjunto de objetos que reducirán la cantidad de código necesario para escribir aplicaciones complejas del lado del navegador. Es independiente de cualquier otro framework que usemos en el cliente, incluso podríamos tener aplicaciones Angular que convivan con aplicaciones KnockoutJs Que es AngularJS?
8 8CONFIDENTIAL El caso de uso ideal para AngularJs son las famosas “Single Page Applications”. Cualquier aplicación en la que necesitamos mucha interacción con el DOM. Su uso NO esta recomendado en el desarrollo de juegos y/o aplicaciones donde la performance es critica, dado que no es un framework optimizado para juegos y a la vez mantiene muchas referencias y observers. Por ultimo, existen muchos benchmarks de complejidad y performance realizados a Backbone, Knockout y Angular. En cuanto a performance, de acuerdo al tipo de escenario cada uno tiene distintas ventajas. Pero, cuando se mide la complejidad del código, Angular suele ser mas simple. Where should I use it?
9 9CONFIDENTIAL −Al principio, se mezclaban los datos y el html en el servidor para luego ser enviados al navgador. De esta forma, secciones enteras de una pagina eran reemplazadas en el cliente. −Ejemplo de este enfoque: ASP.NET Update Panels. −En Angular los templates de html y datos son recibidos en el navegador, y es responsabilidad de AngularJs mezclarlos. Client-Side Templates HTML
10 10CONFIDENTIAL −MVC es el acrónimo de Model – View – Controller, un patrón de arquitectura creado para separar la lógica de datos y negocios, de la de presentación, y de la lógica de eventos e interacción. −Angular fue diseñado con esos principios y provee las siguientes abstracciones: −La vista esta representada por el DOM. −Los controllers son clases de javascript. −El modelo se encuentra almacenado en objetos de javascript. MVC
11 11CONFIDENTIAL −Con el transcurso del tiempo, la mezcla entre datos y html fue trasladada al html, y emergieron las distintas alternativas de client side templates. −Muchos de ellos como plugins de jQuery (ex: jquery-tmpl). −La mayoría de estos plugins consistían en un elemento del DOM oculto (textareas, paragraphs) con el texto del template, mas algunos placeholders para indicar donde irían los datos. Luego esto, sumado a los datos y la ejecución de un método brindarían el resultado final. −Hasta ahí todo genial, perooooo… que pasa cuando nuestros datos cambian en el navegador? O cuando el html generado sirve para cambiar los datos (inputs)?? Data-Binding
12 12CONFIDENTIAL −Mantener el estado del html y javascript es complicado. Data-Binding
13 13CONFIDENTIAL −Angular nos abstrae de toda la lógica necesaria para manejar los cambios en el html y js, utilizando el concepto de databinding. −Angular usa una sintaxis clara en el DOM, lo que hace fácil la creación de templates html, al mismo tiempo que estos elementos traen toda la inteligencia necesaria para actualizar los cambios en los modelos. Data-Binding
14 14CONFIDENTIAL −Una característica muy útil de Angular es la inyección de dependencias. −Angular provee los mecanismos para implementar inyección de dependencias en los distintos servicios, modulos, providers, controllers tanto en los que vienen por defecto, como en los nuevos que crearemos. −El principal objetivo de Angular es extender la funcionalidad de HTML. −Esto es logrado agregando atributos, clases, o usando etiquetas. −Cualquiera de estos elementos que brindan mas inteligencia al DOM son llamados directivas. −Un ejemplo de esto es el atributo ng-model, que agrega la inteligencia necesaria a un input para hacer two-way data-binding. −Lo genial de Angular, es que nos deja crear directivas personalizadas. Inyección de dependencias y directivas
15 15CONFIDENTIAL Estructura de una aplicacion AngularJs02
16 16CONFIDENTIAL Data-Binding Basics Application Entry Point About Views and Controllers Structuring the code: Modules 01 02 03 04
17 17CONFIDENTIAL −Cuando queremos reflejar el valor de un modelo javascript en la vista utilizamos bindings. −El binding mas básico consiste en mostrar el valor en texto plano de un modelo, esto se logra usando llaves dobles “{{}}”.Ejemplo: {{bienvenida}} Data-Binding Basics
18 18CONFIDENTIAL −Ejemplo en: Examples/AppStructure/textbinding.html −Las llaves dobles encierran una “expresión de angular”, el resultado de dicha expresión es visualizado. No nos provee un mecanismo para actualizar dicho modelo, es de solo lectura. −Si deseamos realizar un binding que nos habilite para cambiar los valores del modelo usamos el atributo ng-model. La única condición para su uso es que el elemento del DOM utilizado posea la propiedad value. −Ejemplo en: Examples/AppStructure/basicbindings.html Data-Binding Basics
19 19CONFIDENTIAL Data-Binding Basics
20 20CONFIDENTIAL −Cuando desarrollamos utilizando AngularJs, podemos indicar el elemento del DOM desde el cual queremos que se ejecute la aplicación que estamos escribiendo. −Esto es realizado utilizando el atributo “ng-app”. −Ventajas: −Se pueden usar distintos frameworks MVVM en distintas porciones de la pagina, sin problemas de contexto. −Disminución del árbol de DOM donde Angular debe buscar bindings. −Claridad en el código. −Desventajas −Realiza la detección en el evento onload. No es funcional a cargas asincrónicas de AngularJs. Application Entry Point
21 21CONFIDENTIAL −Revisemos el ejemplo anterior: 1.Describimos una función llamada CrazyController, que recibe un parámetro $scope, y setea una propiedad numeroMagico. 2.En el div con clase jumbotron agregamos el atributo ng-app indicando que aquí comienza una aplicación de AngularJs. 3.Al mismo tiempo agregamos el atributo ng-controller con el valor CrazyController, de esta manera, especificamos que desde este elemento se ejecutara el controller CrazyController. 4.Declaramos un two-way binding sobre la propiedad numeroMagico en el input, para de esta manera leer y modificar el valor de la misma. 5.Declaramos una expresión de angular sobre un span para leer el valor de la propiedad numeroMagico. Application Entry Point
22 22CONFIDENTIAL −Cosas locas: 1.No declaramos en ningún lugar un id o clase que referenciamos en código. 2.No hicimos referencia a ningún evento onload del navegador. 3.No creamos ningún event listener sobre los elementos html. 4.Tampoco escribimos ningún código para manejar la lectura/escritura de propiedades de js. 5.El controller se creo sin utilizar ningún tipo de constructor provisto por angular. 6.El parámetro $scope que recibió el controller no fue instanciado por nosotros y tampoco necesitamos conocer su implementación. Application Entry Point
23 23CONFIDENTIAL −Por defecto AngularJs trae un sistema de ruteo similar al de los frameworks MVC utilizados en backend. −Ejemplo en : Examples/AppStructure/viewsandcontrollers.html −Esto es, cada url del navegador se corresponde con un controller y vista. About views and controllers
24 24CONFIDENTIAL −AngularJs se encarga de detectar los cambios de url, y consecuentemente reemplazar la vista y controller. About views and controllers
25 25CONFIDENTIAL −AngularJs funciona bajo el concepto de módulos. −Un modulo no es mas ni menos que una bolsa que contiene distintos tipos de objetos que comparten una característica, ya sea lógica o por tipo de objeto. −Usar módulos siempre fue una buena practica en programación, ya que ayuda a mantenernos DRY, y a la vez proporciona de una estructura al código que hace mas fácil su mantenimiento. −Para crear un modulo en angular, usamos angular.module(nombre, [dependencias]). El primer parámetro del constructor es el identificador del módulo, y el segundo (opcional) la lista de dependencias. Modules
26 26CONFIDENTIAL Modules03
27 27CONFIDENTIAL Dependency Injection Module Artifacts Module Dependencies 01 02 03
28 28CONFIDENTIAL Revisemos el controller que declaramos en el primer ejemplo: −$scope representa el contexto del controller, mas tarde veremos en detalle el manejo de contextos en AngularJs. −Como sabemos que $scope representa el contexto? Si el primer parámetro tuviera otro nombre seria también el contexto? Como sabe angular que estamos modificando el contexto? Como se crea el objeto? −La respuesta a todo esto es Inyección de dependencias. AngularJs implemento un contenedor de inyección de dependencias basado en tokens. Dependency Injection
29 29CONFIDENTIAL Como funciona la inyección de dependencias en AngularJs? Angular maneja el concepto de providers. Un provider es un objeto que consta de 2 partes. 1) El nombre del objeto. En el caso de $scope, su nombre seria ‘$scope’ 2) Una ‘factory’: Nada mas que una función que devuelva una nueva instancia del objeto, lo que conocemos tradicionalmente como constructor. Entonces, como es realizada la inyección en el controller? 1.Angular encuentra nuestro CrazyController y revisa los parámetros que recibe. 2.Busca si tiene un provider con el nombre ‘$scope’, de ser asi genera una nueva instancia o devuelve la existente. Que hay de otros parámetros que queramos recibir? Todos los objetos que se manejan dentro de angular siguen la forma de provider, y para usarlos en el controller debemos recibir parámetros con el nombre del mismo. Dependency Injection
30 30CONFIDENTIAL Repasemos como crear un modulo de angular. Ejemplo en: Examples/Modules/modules.html Luego de configurar el modulo con config, creamos dos controllers (indexCtrl y otroCtrl), este es solo un tipo de objeto de los muchos que tenemos disponibles en angular. Module Artifacts
31 31CONFIDENTIAL Los tipos de objetos que podemos crear en un modulo de angular son: Controladores =>.controller(‘nombre’,function(dependencias)) Servicios =>.factory(‘nombre’,function(dependencias)) Providers =>.provider(‘nombre’,function(dependencias)) Directivas =>.directive(‘nombre’,function(dependencias)) Filtros =>.filter(‘nombre’,function(dependencias)) Todos estos tipos responden a la misma sintaxis de creación. Module Artifacts
32 32CONFIDENTIAL Una buena practica es crear un modulo para cada tipo de objeto que vamos a utilizar, esto es, un modulo de servicios, controllers, directivas y filtros. Con respecto a los providers, después veremos que son una generalización del concepto servicio. Module Dependencies
33 33CONFIDENTIAL Supongamos que decidimos crear dos módulos, uno para agrupar toda nuestra capa de lógica de negocios (servicios) y otro para agrupar controllers. En este momento contamos con 3 módulos. services: Representa nuestra capa de lógica de negocios y agrupa servicios. controllers: Agrupa los controllers, y para funcionar, necesita tener el modulo services. redditTv: Representa nuestro modulo principal, pues esta referenciado en el html y depende de ‘controllers’ y ‘services’. De esta forma podemos cambiar nuestro modulo/capa de servicios sin afectar otros módulos. Podemos intercambiar dos módulos que tengan el mismo nombre. Reusar un mismo modulo en diferentes aplicaciones de AngularJs. Module Dependencies
34 34CONFIDENTIAL Separar funcionalidad que hará mas fácil el unit testing. Module Dependencies
35 35CONFIDENTIAL Scopes04
36 36CONFIDENTIAL Definition Root Scope Controller Scope Scopes Hierarchy Application Demo Asynchronous Updates 01 02 03 04 05 06
37 37CONFIDENTIAL Scope, representa el contexto javascript que el elemento actual de html tiene disponible. En otras palabras, el scope es el único objeto publico que une el modelo javascript al html. Este objeto puede ser accedido libremente tanto por la vista como por nuestro controller o directiva. Cuando nuestro html se encuentra dentro de una declaración ng- controller, esta usando el scope de ese controller. La creación de propiedades puede ser implicita, y esto facilita/confunde que usemos propiedades que todavía no declaramos. Próximo ejemplo en: Examples/Scopes/apprun.html Definition
38 38CONFIDENTIAL Como en todo contexto, existen distintos niveles/jerarquias. Hasta ahora solo hemos visto el contexto de un controller, pero tambien existe un contexto global o ‘$rootScope’. Root Scope
39 39CONFIDENTIAL En rootScope se crearan las propiedades / métodos en caso que no haya un scope de controller o directiva presente. En la jerarquía de scopes $rootScope es el mas general, se diría que engloba todo lo que se encuentre dentro de ng-app. En el siguiente ejemplo usaremos el método run del modulo principal. Este método sirve para poner todo lo que deseamos ejecutar cuando se inicializa el modulo. Asignaremos la variable local en el $rootScope y veremos cuanto cambia el ejemplo anterior. Sobre $ y $$: Las propiedades / métodos que inician con $ son los métodos públicos de angular, y a su vez los que llevan $$ los privados. Root Scope
40 40CONFIDENTIAL Root Scope
41 41CONFIDENTIAL Vimos que al crear un controller, automáticamente creamos un $scope para el mismo, y a su vez también conocimos en que situaciones aparece $rootScope y como asignarlo Que relación hay entre los scopes de controllers y el rootScope? Al referenciar una propiedad en nuestro html, angular: 1.Busca si existe esta propiedad en el scope local (supongamos, el scope del controller). 2.Si no esta en nuestro scope local, busca en el $rootScope. 3.Si no esta definida en nuestro $rootScope, declara esta propiedad en el $scope local. Mas adelante veremos que este modelo se repite en escenarios mas complejos, pero por el momento con el siguiente diagrama alcanza para ilustrar. Próximo ejemplo en: Examples/Scopes/ngcontroller$rootscope.html Controller Scope
42 42CONFIDENTIAL Controller Scope Index ControllernumeroM $rootScope
43 43CONFIDENTIAL En el ejemplo anterior vimos como, al no encontrar el valor en el $scope del controller, accedió al $rootScope, que si mantenía definida la propiedad numeroM. Ahora, supongamos que tenemos controllers anidados. Código en: Examples/Scopes/nestedControllers.html Scopes Hierarchy
44 44CONFIDENTIAL Scopes Hierarchy PrimerCtrl SegundoCtrl rootScope
45 45CONFIDENTIAL Scopes Hierarchy Ahora, definamos las siguientes propiedades en los distintos scopes
46 46CONFIDENTIAL Scopes Hierarchy Consultemos sus valores en el DOM.
47 47CONFIDENTIAL Scopes Hierarchy
48 48CONFIDENTIAL Desarrollaremos una aplicación para obtener y reproducir los videos publicados en Reddit. Application Demo
49 49CONFIDENTIAL La aplicación estará por el momento dividida en 2 módulos: 1.App.js donde pondremos las configuraciones. 2.Controller.js, que agrupara los controllers. El código antes de las modificaciones esta en ‘Ejercicios/ejercicio0’. En esta primera etapa realizaremos 2 ejercicios: 1.Cargaremos y mostraremos una imagen utilizando ‘ng-src’. 2.El usuario ingresara la url de un video y el mismo será reproducido usando el tag disponible en HTML5 http://www.w3schools.com/html/html5_video.asphttp://www.w3schools.com/html/html5_video.asp Application Demo
50 50CONFIDENTIAL Application Demo Estructura del código antes de las modificaciones
51 51CONFIDENTIAL Angular provee los atributos ng-src y ng-href para utilizar en caso que querramos cargar / enlazar un recurso. Ejemplo en: Examples/Scopes/ngsrc.html Por que usar ng-src y no src=“{{expresión}}”?. Si usamos src=“{{expresión}}” 1.El navegador compila el DOM y comienza a censar que recursos deberá cargar. 2.AngularJs comienza a recorrer el DOM después del evento onload. A esta altura el navegador ya solicito {{expresión}} literalmente. 3.AngularJs cambia src por el resultado de {{expresión}}, en algunos navegadores se piden de nuevo los recursos, en otros no. Application Demo
52 52CONFIDENTIAL Ejercicio 1: Cargar una imagen creando una propiedad en el scope del controller (controllers.js) y realizar un binding en la vista. Una vez terminado el primer ejercicio, podemos bajar el código resuelto yendo a ‘Ejercicios/ejercicio1’. Antes de pasar al siguiente ejercicio hacemos un pequeño repaso sobre el tag : 1.El atributo controls determina que el navegador mostrara los controles para play/pause y volume. 2.En caso que haya una sola URL para el video se puede indicar como atributo src. 3.Dentro del tag video podemos incluir una lista de cada una para el tipo de formato en el cual tengamos disponible el video. 4.Un texto, que se mostrara en caso que la etiqueta no sea soportada. Application Demo
53 53CONFIDENTIAL Ejercicio 2: 1.Crear un text input donde el usuario ingresara la url de un video en formato mp4/ogg (usar bindings). 2.Cargar el video que se encuentra en dicha url usando (ng-src binding). 3.http://upload.wikimedia.org/wikipedia/commons/2/2d/Spinning_hardboiled_egg_01.og ghttp://upload.wikimedia.org/wikipedia/commons/2/2d/Spinning_hardboiled_egg_01.og g 4.http://w3schools.com/html/movie.ogghttp://w3schools.com/html/movie.ogg Para revisar si hemos terminado bien el segundo ejercicio revisamos en “Ejercicios/ejercicio2” Application Demo
54 54CONFIDENTIAL Application Demo
55 55CONFIDENTIAL AngularJs agrego en la ultima version, algo llamado “Strict Contextual Escaping” que, en pocas palabras no permite cargar recursos que se encuentren fuera del dominio (por medidas de seguridad). En el codigo del repo se encuentra deshabilitado. Si tienen curiosidad revisen en app.js, en el metodo.config Application Demo
56 56CONFIDENTIAL Una situación con la que seguramente nos encontraremos, es la de manejar código externo a nuestra aplicación. (plugins, frameworks, libraries). Este tipo de código es muy probable que acceda a algún recurso (DOM, localStorage, XHR) o realice alguna tarea que lleve cierto tiempo. Como programadores en javascript, estamos acostumbrados a setear callbacks, promises, listeners, etc para manejar este tipo de situación y realizar alguna acción al consumir lo que nos brinde este código externo. El problema con esto es que, el código externo, al no encontrarse en el contexto de angular y ser asincrónico, resultara en que nuestros bindings no sean refrescados en la vista. Asynchronous Updates
57 57CONFIDENTIAL Ejemplo: Queremos mostrar un super gif, la tengo fija con reddit… 1.Usando el viejo conocido $.ajax de jQuery hacemos un request a http://www.reddit.com/r/funny/top.json. http://www.reddit.com/r/funny/top.json 2.Ejemplo en: Examples/Scopes/asyncrhonousBefore.html 3.En success seteamos la variable $scope.imageUrl con la url del primer reddit que encontremos. 4.$scope.imageUrl esta bindeada con ng-src en un tag img. 5.Suena todo ok, no? Asynchronous Updates
58 58CONFIDENTIAL Asynchronous Updates
59 59CONFIDENTIAL Obtuvimos la url de una imagen, pero esto no se actualizo en la vista, xq? Angular ejecuta un código 1.Recorre cada expresión o variable que se encuentra siendo trackeada 2.Cuando encuentra que estas expresiones cambiaron su valor, arma un plan de ejecución, que básicamente, en una sola ejecución, actualiza todos los modelos/vista. −En este caso: 1.Angular ejecuto código. 2.Cuando finalizo su ejecución no habia ningún cambio. 3.Finalizo la evaluación de cambios. 4.A wild callback appears… 5.Modifica valores que angular observa. Cri cri… La proxima vez que ejecutemos código Angular, este detectara el valor de $scope.imageUrl y cargara la imagen. Asynchronous Updates
60 60CONFIDENTIAL Que hacer en estos casos? Código resuelto: Examples/Scopes/asyncrhonousAfter.html $scope.$apply([code with changes]); es un método nativo de Angular que desencadena la evaluación de cambios. 2 formas de invocarlo: 1.Después de ejecutar código que no será alcanzado por la evaluación. 2.Pasando como parámetro la función que realiza los cambios en el scope. Asynchronous Updates
61 61CONFIDENTIAL Data Binding05
62 62CONFIDENTIAL Two-way binding ng-click Watchers ng-repeat $http Implicit Scopes & Messaging 01 02 03 04 05 06
63 63CONFIDENTIAL A lo largo de los distintos ejemplos vimos como realizabamos un binding entre la vista y el controller, un modelo que representaria la relacion seria el siguiente: Two-way binding Vista $scope controller
64 64CONFIDENTIAL Todo bien, pero hasta ahora la única interacción directa que vimos con el controller fue a través de un input. Ejemplo: Nuestro controller tiene una lógica super mega compleja y queremos mantener la vista actualizada todo el tiempo. Examples/Bindings/critico.html Two-way binding
65 65CONFIDENTIAL Veamos mas interacción con el usuario, como bindeamos acciones en elementos clickeables? ng-click es un atributo que establece un binding en onclick. Ejemplo en: Examples/Bindings/ngclick.html ng-click
66 66CONFIDENTIAL Otra forma de binding con ng-click es poniendo como valor expresiones. Ejemplo en: Examples/Bindings/ngclick2.html ng-click
67 67CONFIDENTIAL Con angular tenemos la posibilidad de declarar observers sobre propiedades. Exploremos el siguiente caso de uso 1.Tenemos una lista de productos con 3 columnas: Descripción, Precio, Precio con impuesto. 2.Necesitamos guardar la lista de precios. 3.El impuesto varia de acuerdo al tipo de cliente, o… 4.El impuesto puede ser ingresado a mano. Watchers
68 68CONFIDENTIAL Watchers Ejemplo en: Examples/Bindings/watchers.html
69 69CONFIDENTIAL Una forma fácil de resolver esto es calcular el precio con impuesto de la siguiente forma: {{productos[0].Precio * (1 + tasa / 100) }}, pero de esta manera no estamos guardando el valor en el objeto. Para estos casos tenemos la funcion $watch: $scope.$watch(‘expression que queremos observar’, [callback donde va la magia]); En nuestro caso particular: $scope.$watch(‘tasa’, function(newValue, oldValue){ foreach….. cambiar precio }); Watchers
70 70CONFIDENTIAL Watchers Ejemplo en: Examples/Bindings/watchers2.html
71 71CONFIDENTIAL En muchas situaciones necesitamos mostrar y manipular listados en la web. Cuando realizamos estas iteraciones creamos n veces la misma estructura de DOM. ng-repeat es un atributo (directiva) creado con tal fin, la sintaxis es bastante simple: …. Ejemplo: Mostraremos el listado anterior de productos usando ng-repeat. Código en: Examples/bindings/ngrepeat.html ng-repeat
72 72CONFIDENTIAL ng-repeat
73 73CONFIDENTIAL Ejercicio 3: Mostrar la lista de productos anterior usando ng-repeat. El codigo necesario se encuentra en: “ejercicios/ejercicio3” Una vez terminado, el codigo resuelto esta en “ejercicios/ejercicio3fin” ng-repeat
74 74CONFIDENTIAL Para comunicarnos con el backend angular nos provee el servicio $http. La sintaxis es la siguiente: $http({method:’GET’, url:’www.someurl.com’})url:’www.someurl.com’}.success(function(data, status, headers, config){}).error(function(data, status, headers, config){}); Ejemplo: Traeremos el feed de reddit/r/funny usando $http. Examples/bindings/http.html $http
75 75CONFIDENTIAL Shortcuts methods: $http.get(url, config); $http.post(url, data, config); $http.jsonp(url, config); $http.put(url, data, config); $http.delete(url, config); $http.head(url, config); Ejercicio 4: Traer el feed multimedia de www.reddit/r/funny utilizando $http y mostrar el json resultante “crudo” en la pagina. El codigo necesario se encuentra en: “ejercicios/ejercicio4”www.reddit/r/funny Una vez terminado, el código resuelto esta en “ejercicios/ejercicio4fin” $http
76 76CONFIDENTIAL Ejemplo: Del json obtenido anteriormente mostraremos un video. Código en: Examples/bindings/singleVideo.html $http
77 77CONFIDENTIAL Ejercicio 5: Con el feed obtenido en el ejemplo anterior y usando ng- repeat mostrar un listado de “titulo/thumbnail”. El codigo necesario se encuentra en “ejercicios/ejercicio5” Una vez terminado, el código resuelto esta en “ejercicios/ejercicio5fin” $http
78 78CONFIDENTIAL Directives06
79 79CONFIDENTIAL Definition Built-in directives Structure Link: Element Link: Scope Attrs Moving html to directives Building a modal The video directive 01 02 03 04 05 06 07 08 09
80 80CONFIDENTIAL Una directiva es un objeto que extiende las capacidades de un elemento html particular. La forma de crear controles en angular es a través de directivas. Una directiva esta compuesta por dos grandes partes el template y la lógica. Angular viene con varias directivas creadas por defecto (ng-app, ng- controller, ng-model, {{}}…) Definition
81 81CONFIDENTIAL En esta sección veremos algunas directivas que vienen por defecto: ng-show / ng-hide ng-class ng-disabled Ejemplo de sintaxis de las siguientes directivas en: ‘Examples/directives/builtindirectives.html’ Ng-show/hide: Es una directiva que oculta o muestra un elemento basandose en el valor de una propiedad en js. Sintaxis: ng-show=“{{expression}}” / ng-show=“propiedad” Built-in directives
82 82CONFIDENTIAL Ng-class: Es una directiva que setea clases de css basándose en una condición lógica o propiedad en el modelo js. Sintaxis: ng-class=“{ ‘class1’:propiedad1, ‘class2’: propiedad2 }” ng-class=“class1 class2 class3” ng-class=“[array]” Ng-disabled: Esta directiva agrega el atributo disabled a un elemento, basándose en una propiedad o condición lógica Sintaxis: ng-disabled=“{{expression}}” / ng-disabled=“propiedad” Built-in directives
83 83CONFIDENTIAL Ejemplo de directiva en el que mostramos todas las opciones que veremos en este curso: Structure
84 84CONFIDENTIAL Ejemplo: Crearemos una directiva que al poner nos devolverá un paragraph con el texto «test» adentro. El código para este ejemplo en: ‘Examples/directives/basic.html’ Sintaxis: «module».directive(‘name’, factory); Factory: Array de dependencias, con el ultimo elemento como función anónima (lo mismo que usamos para controllers). La buena practica sugiere siempre devolver un objeto con la definición de la directiva. Objeto de definición: En la versión mas simple de la directiva contiene Template: string con el html que mostrara la directiva, es posible que no usemos esta propiedad (por ej ng-show solo agrega «display:block/none;», por ende una directiva puede contener un template o no. TemplateUrl: opcional a Template, en este caso pasamos la url en donde se encuentra el html. Structure
85 85CONFIDENTIAL Replace: Indica si template debe reemplazar completamente al elemento que invoca la directiva, en caso que replace=false el template se insertara como hijo del elemento que invoco la directiva. Restrict: Indica la forma en la que llamaremos a la directiva A: La directiva será invocada por medio de un atributo, (en el ejemplo: ) E: La directiva será invocada como un elemento/tag custom (en el ejemplo ) C: La directiva será invocada usando una clase de css ( ) Pueden admitirse simultáneamente distintas formas: ‘AEC’ La directiva siempre es invocada por su nombre («test») El nombre de la directiva debe ser en formato camelCase Para invocar se normaliza el nombre en notación separada por guiones, por lo que una directiva con name ‘camelCase’ deberá invocarse como ‘camel-case’. Se admite el prefijo ‘data-’ en todas las formas de invocación. Structure
86 86CONFIDENTIAL Link: función que se ejecuta luego de la compilación de la directiva, es el que contiene toda la lógica de la directiva. Recibe tres parametros (scope, element, attrs): con element refiriéndose a la directiva y attrs a sus atributos normalizados. Structure
87 87CONFIDENTIAL Ejercicio: Armar una directiva que al llamarla devuelva Es el sexto ejercicio. No debe admitir ni tampoco El código necesario en ‘Ejercicios/ejercicio6’ El código resuelto en ‘Ejercicios/ejercicio6fin’ Structure
88 88CONFIDENTIAL En este ejemplo veremos como podemos trabajar con el DOM de la directiva. El segundo parámetro del método link, es el elemento actual de la directiva, al mismo podemos realizar cualquier tipo de modificación. El elemento ya viene envuelto en un objeto jQuery por lo cual no necesitamos generar un objeto de ese tipo. En caso que no hayamos agregado jQuery a nuestra app, será un objeto jqLite con propiedades similares. Ejemplo: Cambiaremos el DOM de la directiva del ultimo ejercicio para agregarle un link a google.com 10 segundos luego de que la directiva es mostrada por el navegador. ‘Examples/directives/element.html’. Transforming DOM
89 89CONFIDENTIAL Transforming DOM
90 90CONFIDENTIAL Ejercicio 7: Del ejercicio anterior, una vez parseada la directiva, mover el DOM de manera tal que quede como hijo directo de la etiqueta Código necesario: ‘Ejercicios/ejercicio7’ Código resuelto: ‘Ejercicios/ejercicio7fin’ Transforming DOM
91 91CONFIDENTIAL Como dijimos anteriormente, el método link almacena la lógica de la directiva. Al tener su propio scope, en una directiva aplican las mismas reglas que vimos en el caso de controllers. Ejemplo: Transformaremos el ejemplo de suma/resta en una directiva Código en: ‘Examples/directives/sumaResta.html’ Link: scope
92 92CONFIDENTIAL Link: scope
93 93CONFIDENTIAL Existen dos formas de comunicarnos con el exterior, ahora repasaremos como comunicarnos a través de atributos. Revisemos el ejemplo anterior, y supongamos que el valor inicial de la directiva, es recibido desde el controller. Agregaremos un atributo a la directiva llamado valorInicial, que contendra la variable que deseamos leer. Como valor de este atributo, pasaremos el valor de primerValor en el controller. Si revisamos en nuestra directiva, tendremos el valor resuelto en ‘attrs’ de la siguiente forma: attrs.valorInicial. Código en: Examples/directives/sumaRestaAttrs.html Attrs
94 94CONFIDENTIAL Dos cosas a notar: cuando pasamos el valor lo hicimos a través de {{}}, esto es xq quisimos pasar solo el valor. Al recibir solo texto, hicimos parseInt(attrs.valorInicial); Que pasa si queremos mantener nuestro valor actualizado con el del controller? Ejemplo: Examples/directives/sumaRestaAttrsParse.html En el caso de usar attrs, necesitaremos utilizar el servicio $parse de angular. $parse recibe una expression y devuelve un objeto del cual se pueden obtener dos metodos. Getter = $parse(expression) Setter = $parse(expression).assign; Para ejecutar cualquiera de los metodos es necesario pasar el scope como primer parametro, para que de esta forma angular pueda evaluar el valor de la expression en ese contexto. Attrs
95 95CONFIDENTIAL Ventajas: Obtenemos un objeto con el valor y tipo. No necesitamos castear un string al tipo de objeto que necesitamos. En el markup utilizamos propiedades en el scope de la directiva. (las que parseamos) Podemos pasar cualquier tipo de expresión. Desventajas El scope externo debe ser accesible desde la directiva. No se respeta el encapsulamiento del controller. Cualquier directiva puede modificar valores del scope sin permiso previo. No queda claro a primera vista en que atributos se reciben parametros. Es posible que usemos propiedades que esten en otros scopes si no somos cuidadosos. Attrs
96 96CONFIDENTIAL Ejercicio: Crear una directiva que dado un objeto recibe un objeto del tipo video, muestra su thumbnail y caption. Código necesario para iniciar en ‘Ejercicios/ejercicio8’ Este es el markup que utilizamos anteriormente para mostrar el thumbnail y caption. El código resuelto en ‘Ejercicios/ejercicio8fin’ Link: scope
97 97CONFIDENTIAL Otra forma de comunicarnos con las directivas es a través de la propiedad scope. En los ejemplos anteriores, si desde el markup haciamos referencia a cualquier propiedad del controller podiamos acceder a la misma (idem desde el código). La directiva deja de ser independiente y se dificulta reusarla en otros lugares. Para estos casos creamos scopes isolados. Esto es realizado asignando un objeto a la propiedad scope. Ejemplos: Examples/directives/publicScope.html, Examples/directives/isolatedScope.html Scope
98 98CONFIDENTIAL En el ejemplo con scope isolado, vemos como desde el markup no accedemos a los scopes que se encuentran fuera de la directiva. Como nos comunicamos con los scopes externos? Declaramos que propiedades de nuestro scope local se relacionaran con el scope externo. Por cada propiedad indicamos el tipo de binding: Text, read-only: ‘@’ Two-way binding: ‘=‘ Puntero a función: ‘&’ Indicamos que atributo en la invocación de la directiva se corresponde con la propiedad declarada. Ejemplo: scope: { propiedad1: ‘@nombreAtributo’ } Si no se incluye el nombre del atributo, se asume q es el mismo nombre de la propiedad. scope: { propiedadNueva : ‘@’ } buscara su valor en un atributo propiedad- nueva=‘valor’ Scope
99 99CONFIDENTIAL Ejemplo: Modificaremos el ejemplo anterior de suma y resta, pasando el valor inicial a un scope isolado. ‘Examples/Directives/sumaRestaIsolated.html’ Observación, si seteamos: propiedad: ‘=‘ en html sera propiedad=‘controllerProperty’ propiedad: ‘@’ en html sera propiedad=‘{{controllerProperty}}’ propiedad: ‘&’ en html sera propiedad=‘controllerMethod(params)’ Ejemplo: El método para restar será provisto por el controller. ‘Examples/Directives/sumaRestaMethodBinding.html’ Scope
100 100CONFIDENTIAL Services07
101 101CONFIDENTIAL Definition angular.module.factory Creating a service on top of $http Using services in controllers/angular artifacts Minification issues on injection $timeout $timeout.cancel Example sharing data across controllers Refactor of previous ng-controller example Services
102 102CONFIDENTIAL Routing08
103 103CONFIDENTIAL Definition Partial Views Setting routes Ng-view $routeProvider When(route, config) Otherwise Controller Routing
104 104CONFIDENTIAL Template TemplateUrl $templateCache $routeParams Routing
105 105CONFIDENTIAL Filters09
106 106CONFIDENTIAL Definition Pipe $filter Multiple filters Date, currency Filter Json LimitTo Filters
107 107CONFIDENTIAL Lowercase Number Orderby Uppercase Create your own filter Filters
108 108CONFIDENTIAL Forms10
109 109CONFIDENTIAL Unit Testing11
110 110CONFIDENTIAL
111 111CONFIDENTIAL Resources Appendix A −Performance Benchmarks −Backbone vs Ember http://jsfiddle.net/jashkenas/CGSd5/http://jsfiddle.net/jashkenas/CGSd5/ −Backbone vs Ember vs AngularJs http://jsfiddle.net/mhevery/vYknU/23/ http://jsfiddle.net/mhevery/vYknU/23/ −Another benchmark and the point of view of Misko Hevery (Angular Dev) https://groups.google.com/forum/#!topic/angular/95Jctop_nJ4 https://groups.google.com/forum/#!topic/angular/95Jctop_nJ4 −Complexity of several TODOMVC implementations http://blog.coderstats.net/todomvc-complexity/ http://blog.coderstats.net/todomvc-complexity/
112 Color palette TOOLKIT Charts Elements Chart Element 4 Chart Element 3 Chart Element 2 Chart Element 1 Chart Element 4 Chart Element 3 Chart Element 2 Chart Element 1
113 ICONS ApplicationsCloudConnections Desktop Support Mobile Tablet PeoplePerson Server AdapterAndroidAppleCustomer Location DatabaseFlat Screen TV Set-Top BoxWindows Laptop ApplicationsCloudConnections Desktop Support Mobile Tablet PeoplePerson Server AdapterAndroidAppleCustomer Location DatabaseFlat Screen TV Set-Top BoxWindows Laptop
114 CONFIDENTIAL©2013 GlobalLogic Inc. Thank you