Angular logo

Utn Rosario

TTADS

Técnicas y Tecnologías Avanzadas de Desarrollo de Software

Ing. Andres Otaduy

HTML + HTTP Paginas Estaticas

Primer pagina web Emulador

Evolucion FrontEnd

HTML + Imagenes + Tablas

Hypermedia: HTML + Imagenes + Tablas

Web Applications

Perl, ASP, PHP, Apache, MySQL

Single Page Applications

NodeJs, Java, C#, MongoDB, Javascript, REST API

SPA: Single Page Applications

  • Servicios REST
  • Frameworks Front End Angualr, ember, knockout, React
  • Separacion de Intereses
  • Division de Backend / Frontend
  • Mobile o Mobile First
  • Examples

Javascript

Javascript
  • Uno de los lenguajes mas usados e incomprendidos del mundo
  • Obligatorio para programar en el browser
  • Interfaz Con el DOM
  • Sintaxis de C, Semantica de Scheme

Javascript influencias

  • Scheme
  • Java
  • Self
  • Perl

Javascript Good Parts

  • Loose Typing
  • Objetos Dinamicos
  • Funciones de Orden Superior
  • Funciones Lambda
  • Funciones Clousures
  • Objetos Literales
  • Herencia prototipica
  • Es facil!

Funciones de Orden Superior


                  function paraCada(unArray, unaFuncion) {
                    for (i=0; i < unArray.length; i++) {
                      unaFuncion(unArray[i], i);
                    }
                  }

                  paraCada([10,20,'hola', 'que', 87], function(elem, index) {
                    console.log('Elemento:', elem, index)
                  });

                  function mapear(unArray, unaFuncion) {
                    var answer = [];
                    for (i=0; i < unArray.length; i++) {
                      answer.push(unaFuncion(unArray[i], i));
                    }
                    return answer;
                  }

                  function cuad(a) {
                    return a*a;
                  }

                  console.log(mapear([1,2,3,4,5], cuad));
                

Funciones Lambda

var cuad, cubo, array = [1,2,3,4];
cuad = function(a){
  return a * a;
};
cubo = function(a) {
  return cuad(a) * a;
};
var array = [3,5,7,9,11,14];
array.map(cuad) + array.map(cubo);
console.log(array.reduce(0, suma));

array.filter(function (elem){ return elem > 10})
    .map(function (elem) { return elem * elem });

function suma(a,b) {
  return a + b;
}

Clousures

function makeAdder(a) {
  return function(b) {
    return a + b;
  };
}
var x = makeAdder(5);
var y = makeAdder(20);
x(6); // ?
y(7); // ?

Objetos dinamicos

var object = {name: 'Jon'};
object.lastName = 'Smith';
object.print = function(){
  console.log('Name:', this.name);
  console.log('LastName:', this.lastName)};
object.print();

Objetos Literales

{
  "glossary":{
    "title":"example glossary",
    "GlossDiv":{
      "title":"S",
      "GlossList":{
        "GlossEntry":{
          "ID":"SGML",
          "SortAs":"SGML",
          "GlossTerm":"Standard Generalized Markup Language",
          "Acronym":"SGML",
          "Abbrev":"ISO 8879:1986",
          "GlossDef":{
            "para":"A meta-markup language, used to create markup languages such as DocBook.",
            "GlossSeeAlso":[
              "GML",
              "XML"
            ]
          },
          "GlossSee":"markup"
        }
      }
    }
  }
}

Herencia Prototipica


                var padre = {nombre: 'Pepe', apellido: 'Perez'};
                var hijo = Object.create(padre);
                padre.mostrarNombre = function() { console.log(this.nombre)};
                hijo.nombre = 'Pedro';
                padre.mostrarNombre();
                hijo.mostrarNombre();
                console.log(hijo.apellido);

Clases con Herencia Prototipica

// Shape - superclass
  function Shape() {
    this.x = 0;
    this.y = 0;
  }

  // superclass method
  Shape.prototype.move = function(x, y) {
    this.x += x;
    this.y += y;
    console.info('Shape moved.');
  };

  // Rectangle - subclass
  function Rectangle() {
    Shape.call(this); // call super constructor.
  }

  // subclass extends superclass
  Rectangle.prototype = Object.create(Shape.prototype);
  Rectangle.prototype.constructor = Rectangle;

  var rect = new Rectangle();

  console.log('Is rect an instance of Rectangle?',
    rect instanceof Rectangle); // true
  console.log('Is rect an instance of Shape?',
    rect instanceof Shape); // true
  rect.move(1, 1); // Outputs, 'Shape moved.'

Javascript Bad Parts

  • Variables Globales - Scope Global
  • Interfaz con el DOM
  • Insercion de punto y coma
  • comparaciones == !=
  • Es facil!

Correr JS

  • Embebido
  • Scripts
  • NodeJs

Ejercicios

Crear una funcion buscar(array, criterio, siVacio), que reciba un array y dos funciiones si criterio es verdadero devolver el elemento encontrado sino doveolver el resultado de ejecutar la otra funcion "siVacio"

Completar el ejemplo de Shape para que incluya circulos y triangulos, un metodo para mostrar cada uno por consola y un metodo para escalar cada figura en un porcentaje

Angular.js

  • Framework front end Opinionated
  • Templates Declarativos
  • Extiende HTML
  • Componentes
  • Testeabilidad
  • Alto Nivel
  • Aplicaciones ABM
  • MVC - MVVM
  • Facil de instalar
  • Algunas Desventajas

Templates Declarativos

Extiende HTML

<div class="row">
    <h2>Search movies</h2>
</div>
<div class="row">
    <div class="col-xs-12">
        <search-box autocomplete="searchVm.topMovieNames" search-callback="searchVm.updatedSearch"></search-box>
        <movie-listing  movies="searchVm.movies"></movie-listing>
    </div>
</div>
<div class="row">
</div>
<home-footer></home-footer>

Componentes

Testeabilidad


Angular.js

  • Alto Nivel
  • Aplicaciones ABM
  • MVC - MVVM
  • Facil de instalar
  • Algunas Desventajas

Como Empezar

Cargar el script de angular, usar la directiva ng-app

<!doctype html>
                <html ng-app>
                <head>
                <title>My Angular App</title>
                <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
                </head>
                <body>
                <!-- Add your template here -->
                </body>
                </html>

Estructura

Views - Templates - Directivas

  • Two way binding {{}}
  • Directivas del Framework
    • ng-app
    • ng-init
    • ng-model
    • ng-if, ng-show
    • ng-repeat
    • ng-class

words

Data Binding

  1. Compilacion del template
  2. Cambio en la vista actualiza el modelo
  3. Cambio en el modelo actualiza la vista ir a 2
  4. Cuando modelo y vista estan estables render del DOM

Todo List

Filters

Es una funcion sin efectos secundarios que toma un valor del template o de otro filtro y lo reemplaza por otro.

Sintaxis: {{expresion | filter1: param1 : param2 | filter2 : param21 | filter3 ...}}

  • currency
  • number
  • orderBy
  • json
  • limitTo
  • filter

Ejercicio

Ordenar alfabeticamente los elementos del Todo List. Agregar un color de fondo gris a los elementos que estan completados del todo list.

Controllers

MVC Model View Controller vs MVVM Model View ViewModel

scope

  • El contexto de ejecucion de una view
  • Puede alojar estado y comportamiento
  • Organizado jerarquicamente
  • Puede disparar eventos
  • Encargado del Two way binding

Controller

  • Aumentan el scope con funciones y estado
  • Setean el estado inicial e una vista
  • ng-controller
  • Controller y Scope
  • Estilo
  • ng-include

Ejemplo

Ejercicio

Modificar el ejemplo en User List para:

  • Agregar los campos de apellido y telefono y mostrarlos en la lista
  • Agregar un boton para cambiar el password del usuario usar la funcion prompt() para obtener el password
  • Agregar un boton que permita eliminar todos los elementos seleccionados
  • Agregar un campo para mostrar la edad en la lista y ordenar la lista por este campo

Directivas Basicas

Las directivas son marcadores en el DOM (elementos, atributos, classes o comentarios). Para extender el HTML, modificar el comportamiento de los elementos o de sus hijos.

Angular compila en tiepo de ejecucion los templates buscando directivas y agregando comportamiento a los elementos del DOM.

Directivas - Componentes

  • Tipo de la Directiva EAC
  • Template
  • Scope
  • controllerAs
  • bindToController

Api completa en https://docs.angularjs.org/api/ng/service/$compile

Ejemplo

  angular
        .module('moviesApp')
        .directive('searchBox', searchBoxDirective);
    function searchBoxDirective() {
        return {
            restrict: 'E',
            // template: '
', templateUrl: 'app/components/search-box/search-box.html', scope: { query: '=?', autocomplete: '=', searchCallback: '=' }, bindToController: true, controller: 'SearchBoxController', controllerAs: 'searchVm' }; }

Ejemplo HTML

<div class="row">
    <h2>Search movies</h2>
</div>
<div class="row">
    <div class="col-xs-12">
        <search-box autocomplete="searchVm.topMovieNames" search-callback="searchVm.updatedSearch"></search-box>
        <movie-listing  movies="searchVm.movies"></movie-listing>
    </div>
</div>
<div class="row">
</div>
<home-footer></home-footer>

Otros tipos de directivas

Las veremos mas adelante.

  • Manipulacion del DOM
  • Compilacion
  • Transclusion

Ejercicio

Modificar el ejemplo de la lista de usuarios para usar dos directivas, una para la lista, y otra para el formulario de entrada de los datos

Servicios Angular

Son objetos singleton no visuales con lazy initialization, que se pueden inyectar a traves del sistema de injeccion de dependencias en otros componentes.

  • Comunicar Directivas y Controladores
  • Compartir y Reusar codigo
  • Acceder a las API del browser
  • Manejar la comunicacion HTTP

Servicios Angularjs

Servicios de Angular

  • Browser: $window, $location, $anchorScroll, $timeout
  • Angular: $filter(‘limitTo’), $controller, $log, $rootScope, $scope
  • Templates: $compiler, $parse, $interpolate
  • Promises: $q
  • API Calls: $http, $resource, $xhrFactory
  • Seguridad: $sce, $sceDelegate

Injeccion de Dependencias

Inversion de control, para configurar y testear

  • Dependencia de Creacion: collection = new Array()
  • Variable Global: window.location = ‘http://www.google.com’
  • PAsar como parametro: function factory(collectionClass){ collection = new collectionClass();}

Sintaxis de DI

    // Reflection notation
    angular.module('website').
    controller('PageController', PageController);
    function PageController($scope, $timeout){};

    // $inject notation
    angular.module('website').
    controller('PageController', PageController);
     PageController.$inject = [‘$scope’, ‘$timeout’];
     function PageController($scope, $timeout){};

    // Array notation
    angular.module('website').
    controller('PageController',
      [‘$scope’, ‘$timeout’, function($scope, $timeout){}]
    );
    

Creacion de un servicio

(function() {
    angular
        .module('webapp')
        .factory('socialSharing', service);

    service.$inject = [
        '$window'
    ];

    function service($window) {
        var service = this;
        service.shareWithNetwork = shareWithNetwork;
        return service;

        function shareWithNetwork(name, url, networkFun, label) {
            if (!$window.plugins || !$window.plugins.socialsharing) {
              return reportShareError(label);
            }
            $window.plugins.socialsharing[networkFun](name, null, url, angular.noop, function () {
              reportShareError(label);
            });
          }
        }
}

Ejercicio

Modificar el ejemplo de la lista de usuarios para que utilizando Storage y localStorage la lista de usuarios sea persistente. Crear un servicio angular que encapsule la lista de usuarios y la mantenga actualizada en localStorage. el servicio deberia tener una interfaz con los metodos para agregar, eliminar, actualizar un elemento y obtener la lista de todos los usuarios.

$http

$http permite realizar llamadas http en sus diferentes metodos. devolviendo una promesa por el resultado de la llamada.


  // Simple GET request example:
  $http({
    method: 'GET',
    url: '/someUrl'
  }).then(function successCallback(response) {
      // this callback will be called asynchronously
      // when the response is available
    }, function errorCallback(response) {
      // called asynchronously if an error occurs
      // or server returns response with an error status.
    });

$http respuesta

  • data – {string|Object} response body
  • status – {number} – HTTP status code of the response.
  • headers – {function([headerName])} – Header getter function.
  • config – {Object} – The configuration object
  • statusText – {string} – HTTP status text of the response.

Shortcut

$http.get('/someUrl', config).then(successCallback, errorCallback);
$http.post('/someUrl', data, config).then(successCallback, errorCallback);

$http ejemplos

Promesas - $q

Una promesa es un objeto que representa un valor que puede estar disponible ahora, en el futuro o nunca.

Trabajamos con promesas para computar valores de forma asincrona tomando acciones cuando el valor esta disponible o cuando se produce un error.

Promesas - $q

Una promesa puede tener tres estados, pendiente (pending), resuelto (resolved), rechazado(rejected).

Usando then(), catch(), finally() podemos tomar acciones ante los diferentes estados de la promesa.

Promesas


function(aPromise, $q) {
  aPromise
    .then(successCallback, errorCallback)
    .catch(errorCallback)
    .finally(finallyCallback);
  rejected = $q.reject();
  resolved = $q.when();
  newPromise = $q.all([rejected, resolved, aPromise]);
  newPromise = $q.race([rejected, resolved, aPromise]);
  //Create promises
  deferred = $q.defer();
  deferred.resolve(aValue);
  deferred.reject(aValue);
  return deferred.promise;
}

antipatterns

Anti-patterns


function anAsyncCall() {
  var promise = doSomethingAsync();
  promise.then(function() {
      somethingComplicated();
  });

  return promise;
}

function anAsyncCall() {
    var promise = doSomethingAsync();
    return promise.then(function() {
        somethingComplicated()
    });
}
}

Broken Chain

Anti-patterns

somethingAsync.then(
  function() {
      return somethingElseAsync();
  },
  function(err) {
      handleMyError(err);
});
somethingAsync
  .then(function() {
      return somethingElseAsync();
  })
  .catch(function(err) {
      handleMyError(err);
  });

Keen Error Handler

Anti-patterns

var promise;
if (asyncCallNeeded)
promise = doSomethingAsync();
else
promise = $q.when(42);

promise.then(function() {
doSomethingCool();
});
$q.when(asyncCallNeeded ? doSomethingAsync() : 42)
.then(function(value){
  doSomethingGood();
})
.catch(function(err) {
  handleTheError();
});
}

The Ghost Promise

Anti-patterns

var deferred = $q.defer();
doSomethingAsync().then(function(res) {
  res = manipulateMeInSomeWay(res);
  deferred.resolve(res);
}, function(err) {
  deferred.reject(err);
});

return deferred.promise;
return doSomethingAsync().then(function(res) {
  return manipulateMeInSomeWay(res);
});

The Forgotten Promise

Ejercicio

Crear un juego de ruleta virtual que permita sortear un numero, el numero, el color, y si es par o impar y la docena a la que pertenece. No hace falta mostrar el tablero.
los numeros aleatorios deben generarse usando la APi de random.org ver: Intro y Json rpc api con el metodo generateIntegers.

Numeros Negros: [2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 29, 31, 33, 35]

Numeros Rojos: [1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36]

APi Key: 2d87f134-9c82-4485-a79f-4d2e14129468

UI Router

  • Estados y Views anidadas
  • Vistas multiples
  • Resolves
  • Datos por estadi
  • Parametros URL

Components

$stateProvider / $state ui-sref ui-view $urlRouter / $urlRouterProvider

Basico

template, templateUrl resolve custom-data, $stateParams
                        
  $stateProvider
    .state('movie-page', {
        title: 'Movie',
        url: '/movie/:movieId',
        templateUrl: 'app/pages/movie/movie-page.html',
        controller: 'MoviePageController',
        controllerAs: 'movieVm',
        resolve: {
            movie: ['$stateParams', 'moviesConnector',
                function($stateParams, moviesConnector) {
                  var id = $stateParams.movieId;
                    return moviesConnector.movieInfo(id)
                      .then(function (response) {
                          return response.data;
                      });
                    }]
                  }
                });
              
                      

API basica

  • $stateProvider.state(name, {})
  • $state.go(state, params, {location: true, reload:false, notify:true})
  • $state.get
  • urlRouterProvider
  • ui-view ui-sref

Ejemplo

Agregar una pagina que muestre las peliculas que se estan viendo.

Agregar una pagina que muestre las peliculas que se estan viendo. en se pueden obtener los datos /api/movies/playing usando un resolve para obtener los datos. el componente moviesConnector tiene el metodo para recuperar los datos.

Eventos

  • $stateChangeStart
  • $stateChangeEnd
  • $stateChangeError
  • event, fromState, toState, paramters
  • event.preventDefault() para detener la transicion

Tecnicas

Scope CSS

Agregando una clase que corresponde al estado se pueden acotar los css a cada pagina.

Manejo de Errores

  • Poner un event handler al principio del proyecto
  • Crear un mecanismo de redirectTo

Tecnicas

Manejar Autenticacion y login

Interceptar eventos para proteger paginas.

                        
$rootScope.$on('$stateChangeStart', function(e, to) {
  if (!to.forceLogin) return;
  if (!isLoggedIn($currentUser)) {
    e.preventDefault();
    // Optionally set option.notify to false if you don't want
    // to retrigger another $stateChangeStart event
    $state.go(result.to, result.params, {notify: false});
  }
                        
                      

Manejo de URL

  • urlRouterProvider
  • when(what, String|Function) ret: false|String|true
  • otherwise(String|Function)
  • rule(Function) ret: Set the url

Estados anidados

  • Relacion Padre Hijo
  • Herencia de resolves y datos custom
  • Prefix Url
  • Estados abstractos
  • Notacion punto o propiedad parent
  • El padre debe existir
  • Herencia de Scopes

Estados Abstractos

  • Para concatenar al prinicipio unurl to all child state urls.
  • Para insertar template con sus propiasui-view(s)que los estados hijos van a completar.
  • Para proveer dependencies resueltas via resolve.
  • Para proveer datos heredades via propiedaddata .
  • Para correr callbacks onEnter o onExit que puedan modificar la app de alguna forma.
  • Cualquier combinacion de lo anterior.

Ejercicio

Agregar en angular example:

  • Una pagina /list que muestre las peliculas mas populares.
  • Agregar a la pagina de search los parametros para controlar el orden, por el campo nombre o popularidad y permitir un orden ascendente o descendente