Angular 'n' cookies – by: Ivo Parun Rua, Dario Diaz – Fast JS



Angular 'n' cookies – by: Ivo Parun Rua, Dario Diaz – Fast JS

0 1


presentacionSge

Presentacion de Angular JS para CIDS

On Github darioodiaz / presentacionSge

Angular 'n' cookies

by: Ivo Parun Rua, Dario Diaz

Agenda

Fast JS

  • Javascript y sus trucos
  • JSON
  • Closure scopes

Angular

  • Expression y {{Brackets}}
  • Modules, services, y mas...
  • Scopes y scopes
  • MVC en angular
  • Angular Builts-in
  • DI y buenas practicas
  • Angular routing con ui-router
  • Estructura de carpetas

Agenda

Ending

  • Angular y Jboss
  • Angular y Require JS
  • Sge-components
  • presentation.commit()

Agenda

Fast JS

Javascript y sus trucos

La variable poderosa

Una variable puede ser un valor, funcion, objeto, whatever

Los misterios de undefined

Cualquier valor que no exista se convierte en undefined

Dinamismo everywhere

Cualquier objeto es dinamico, esto es, pueden agregarse nuevas propiedades (atributos y/o metodos) sin que esten definidos previamente

La variable poderosa como funcion

//Creamos una variable que guarde nuestra funcion
var soyUnaFuncion = function() {
	console.log('Js Rulez!');
};
//La llamamos
soyUnaFuncion();

//Puede recibir parametros
var soyUnaFuncionConParametros = function(nombre, apellido) {
	console.log('Hola' + nombre + ", " + apellido);
};
soyUnaFuncionConParametros("Dario", "Diaz");

La variable poderosa como objeto

//Creamos una variable que guarde nuestra funcion constructora
var soyUnConstructor = function(nombre, apellido, miEdad) {
	this.nombre = nombre;
	this.apellido = apellido;
	this.edad = miEdad;
	this.mostrarDatos = function(variableInterna) {
		return this.nombre + " - " + this.apellido + " - " + variableInterna;
	};
};
//Creamos un objeto
var objeto = new soyUnConstructor("Dario", "Diaz", 23);
//Lo usamos como cualquier objeto
console.log(objeto.nombre);
console.log(objeto.mostrarDatos());

Los misterios de undefined

//Creamos una function con 3 parametros
var miFuncion = function(param1, param2, param3) {
	console.log('Parametro 1: ', param1);
	console.log('Parametro 2: ', param2);
	console.log('Parametro 3: ', param3);
};
//La llamamos con un parametro de menos
miFuncion("Hola", "Mundo");

Dinamismo everywhere

//Creamos un objeto por cualquier forma
var miConstructor = function(param1, param2) {
	this.nombre = param1;
	this.apellido = param2;
};
//Creamos un objeto
var miObj = {};
var miObj2 = new Object();
var objeto = new miConstructor("Dario", "Diaz");
objeto.otraPropiedad = 3;
miObj.valorBooleano = true;
miObj2.metodo = function(parametro) {
	console.log("Funcion de miObj2:" , parametro + 1);
};

JSON (JavaScript Object Notation)

Es una forma de describir objetos en JS

Un JSON puede solo tener atributos (ya sean valores, otros objetos, arrays, etc)

La caracteristica fundamental de un JSON es que se puede escribir (materializar) y leer (desmaterializar) como un String

JSON | Ejemplo simple

{
"propiedad": "valor",
"otraPropiedad": 3
}

JSON | Ejemplo completo

{
"propiedad": "valor",
"otraPropiedad": 3,
"array": ["elemento1", "elemento2"],
"objeto": { "idem": true, "idem2": 345 }
}

Conviertiendo objetos en JSON & viceversa

JS nos provee 2 funciones para transformar String en JSON o convertir nuestros objetos en JSON

JSON.parse(string): trata de transformar un string en objeto JSON, si falla lanza excepcion

JSON.stringify(objeto): transforma un objeto en un String JSON

JSON.parse() | Ejemplo

var respuestaDelServer = '{
"propiedad": "valor",
"otraPropiedad": 3
}';
var objParseado = JSON.parse(respuestaDelServer);
console.log(objParseado);

JSON.stringify() | Ejemplo

//Creamos un objeto normal
var obj = {};
obj.nombre = "Dario";
obj["apellido"] = "Diaz";
var parseo = JSON.stringify(obj);
console.log(parseo);

Closure scopes

Scope: ambito o contexto donde co-existen variables y metodos

Closure Scope: expresiones (normalmente funciones o metodos) que pueden acceder a otros ambitos

Closure scopes | Ejemplo

Ejemplo

Angular

Expresiones en Angular

Las expresiones en Angular son sentencias comunes de JS con las siguientes restricciones

  • Cada expresion es evaluada en el scope actual
  • Si la expresion fuera a dar un error o fuera invalida se devuelve null y el programa continua
  • No se permiten sentencias condiconales, ciclos o excepciones
  • Se pueden usar los filtros de Angular o propios definidos en el modulo
  • Si se desea usar una expresion mas compleja, se puede usar $eval proporcionado en el scope

Modules

En Angular un modulo es un conjunto de elementos que coordinan para trabajar

Un modulo Angular puede estar compuesto por

  • Controladores
  • Servicios
  • Directivas
  • Otros modulos

Un modulo Angular se crea de la siguiente forma:

angular.module("NOMBRE", []);

Tambien puede ser guardado en una variable para referirse a el despues

var miModulo = angular.module("NOMBRE", []);

Controladores

Son los encargados de manipular o brindar los comportamientos necesarios para trabajar con las vistas (paginas para los usuarios) y los datos (modelos). Va a ser el encargado de trabajar en un ambito HTML

Para crear un controlador en Angular:

var miModulo = angular.module("NOMBRE MODULO", []);
miModulo.contoller("NombreCtrl", function($scope) {
    //Codigo del controlador
});

Services vs Factory

En Angular hay 2 formas de brindar servicios. Una es por factory y la otra por service

En esencia son los mismos, la diferencia recabe en que angular tiene una estructura para poder utilizar servicios en distintas etapas de la aplicacion. Por ejemplo, si necesitaramos un servicio durante la configuracion del la aplicacion (app.config block) seria necesario un Provider del servicio y un provider contiene un factory que devuevle un service.

Es decir, usar factory o service a niveles de nuestro uso es indiferente, pero a un uso mas avanzado de angular es necesario saber que un service es devuelto por un factory. (mas info web oficial de angular)

var miModulo = angular.module("NOMBRE MODULO", []);
miModulo.factory("NombreFactory", function() {
    //Los factory devuelven un objeto
    var miFactory = {};
    miFactory.servicio = function() { ... }
    return miFactory;
});
var miModulo = angular.module("NOMBRE MODULO", []);
miModulo.service("NombreSrv", function() {
    //Los service devuelven una funcion que sera usada como constructora, esta funcion puede recibir parametros
    var miService = function() {

    };  
    return miService;
});

Scopes y scopes

En angular los scopes trabajan por herencia, es decir, si tenemos anidamiento de scopes/controllers, si una propiedad no existe en el scope hijo se busca en el padre y ambos trabajan sobre el, hasta que el hijo posea la propiedad

Todos los scopes tiene un atributo llamado $root que representa el scope principal del modulo.

Dentro de los controllers se pueden asignar funcionalidad a los scopes a traves de la DI. En angular sus servicios de inyeccion llevan el simbolo $ delante.

MVC en Angular

MVC (Model View Controller)

En Angular la vista (view) es la pagina HTML/JSP

el controlador (controller) es uno de los definidos mediante modulo.controller(...)

el modelo es implicito y se representa mediante el $scope que es un modelo global que puede tener propiedades (funciones, objetos, atributos) que representarian nuestros modelos de datos para trabajar con los Ctrls y las vista

Ejemplo Angular

Angular Builts-in

Directivas vinculantes

Evalúa los datos del modelo y los inserta en el contenido HTML

ng-bind o {{ }}

                            
$scope.todos = [ {accion:'Caminar'}, {accion:'Correr'}]

<div>Hay {{todos.length}} elementos.</div>

<div>
    Hay <span ng-bind="todos.length"></span> elementos.
</div>
                            
                        

ng-bind-template

                            
<div ng-bind-template="Primero: {{todos[0].accion}}. Segundo: {{todos[1].accion}}">

</div>
                            
                        

ng-bind-html

Peligroso! Crea una vinculación utilizando la propiedad innerHTML de un elemento HTML.

                            
$scope.contenidoHTML = '<a href="#" class="btn btn-default">Link</a>';

<div><p ng-bind-html="contenidoHTML"></p></div>

                            
                        

ng-non-bindable

Previene que AngularsJS vincule alguna expression

                            

<div ng-non-bindable="">
    AngularJS usa {{ y }} caracteres como plantilla.
</div>
                            
                        

ng-model

                            

<div id="todoPanel2" class="panel" ng-controller="defaultCtrl">
    <h3 class="panel-header">To Do List</h3>

    <div class="well">
        <div>El primer item es: {{todos[0].accion}}</div>
    </div>
    <div class="form-group well">
        <label for="primerItem">Set First Item:</label>
        <input id="primerItem" name="primerItem" class="form-control" ng-model="todos[0].accion">
    </div>
</div>
                            
                        

Directivas plantilla

El objetivo principal es generar contenido HTML a partir de valores del modelo

ng-cloak

                            
<div class="well">
    <div class="radio" ng-repeat="button in ['None', 'Table', 'List']">
        <label ng-cloak="">
            <input type="radio" ng-model="data.mode" value="{{button}}" ng-checked="$first">
            {{button}}
        </label>
    </div>
</div>
                            
                        

ng-include

src, onload, autoscroll

                            

<ng-include src="'table.html'" onload="" autoscroll=""></ng-include>

                            
                        

ng-repeat

$index, $first, $middle, $last, $even, $odd

                            
<table class="table">
    <thead>
    <tr>
        <th>#</th>
        <th>Acción</th>
        <th>Listo</th>
    </tr>
    </thead>
    <tbody>
    <tr ng-repeat="item in todos">
        <td>{{$index + 1}}</td>
        <td>{{item.accion}}</td>
        <td>{{item.completo}}</td>
    </tr>
    </tbody>
</table>
                            
                        

ng-repeat-start y ng-repeat-end

                            
<div class="panel panel-default">
    <div class="panel-heading" ng-repeat-start="subMenu in data.menu.subMenu">
        <h3 class="panel-title">{{subMenu.titulo}}</h3>
    </div>
    <div class="list-group" ng-repeat-end="">
        <a ng-repeat="item in subMenu.items" class="list-group-item">
            {{item.nombre}}</a>
    </div>
</div>
                            
                        

ng-switch

                            
<div ng-switch="" on="data.mode">
    <div ng-switch-when="Table">
        <table class="table">
            <thead>
            <tr>
                <th>#</th>
                <th>Action</th>
                <th>Done</th>
            </tr>
            </thead>
            <tbody><tr ng-repeat="item in todos" ng-class="$odd ? 'odd' : 'even'">
                <td>{{$index + 1}}</td>
                <td ng-repeat="prop in item">{{prop}}</td>
            </tr>
        </tbody></table>
    </div>
    <div ng-switch-when="List">
        <ol>
            <li ng-repeat="item in todos">
                {{item.action}}<span ng-if="item.complete"> (Done)</span>
            </li>
        </ol>
    </div>
    <div ng-switch-default="">
        Select another option to display a layout
    </div>
</div>
                            
                        

Directivas en elementos (DOM)

ng-class y ng-style

                            
<table class="table">
    <thead>
    <tr>
        <th>#</th>
        <th>Action</th>
        <th>Done</th>
    </tr>
    </thead>
    <tbody><tr ng-repeat="item in todos" ng-class="active">
        <td>{{$index + 1}}</td>
        <td>{{item.action}}</td>
        <td ng-style="{'background-color': lightgreen}">
            {{item.complete}}
        </td>
    </tr>
</tbody></table>
                            
                        

ng-class-even y ng-class-odd

                            
<table class="table">
    <thead>
    <tr>
        <th>#</th>
        <th>Action</th>
        <th>Done</th>
    </tr>
    </thead>
    <tbody><tr ng-repeat="item in todos" ng-class-even="settings.Rows" ng-class-odd="settings.Columns">
        <td>{{$index + 1}}</td>
        <td>{{item.action}}</td>
        <td>{{item.complete}}</td>
    </tr>
</tbody></table>
                            
                        

ng-hide y ng-show

                            
<table class="table">
    <thead>
    <tr>
        <th>#</th>
        <th>Action</th>
        <th>Done</th>
    </tr>
    </thead>
    <tbody><tr ng-repeat="item in todos">
        <td>{{$index + 1}}</td>
        <td>{{item.action}}</td>
        <td>
            <span ng-hide="item.complete">(Incomplete)</span>
            <span ng-show="item.complete">(Done)</span>
        </td>
    </tr>
</tbody></table>
                            
                        

ng-if

                            

    <span ng-if="!item.complete">(Incomplete)</span>
    <span ng-if="item.complete">(Done)</span>

                            
                        

Directivas para Eventos

  • ng-blur
  • ng-change
  • ng-click
  • ng-copy
  • ng-cut
  • ng-paste
  • ng-dblclick
  • ng-focus

Directivas para Eventos

  • ng-keydown
  • ng-keypress
  • ng-keyup
  • ng-mousedown
  • ng-mouseenter
  • ng-mouseleave
  • ng-mousemove
  • ng-mouseover
  • ng-mouseup
  • ng-submit

Directivas para Formularios

AngularJS aporta directivas para realizar la validación de los formularios

AngularJS aplica las directivas para formularios automaticamente cuando encuentra elementos del tipo form, input, select, y textarea.

Para utilizar las validaciones hace falta utilizar el elemento FORM, el atributo NOVALIDATE es utilizado para que los navegadores con HTML5 no realize validaciones y deje todo en manos de AngularJS

                            
<form name="myForm" novalidate="" ng-submit="addUser(newUser)"></form>
                            
                        

Monitoreo del Formulario

  • $pristine true si el usuario no interactuó con el elemento/formulario

  • $dirty true si el usuario interactuó con el elemento/formulario

  • $valid true si el contenido del elemento/formulario es válido

  • $invalid true si el contenido del elemento/formulario es inválido

  • $error provee de información del error producido.

                            

<div>Valid: {{myForm.$valid}}</div>

<button type="submit" class="btn btn-primary btn-block" ng-disabled="myForm.$invalid">OK</button>

                            
                        

CSS utlizado por AngularJS

  • ng-pristine los elementos con los que no interactuó el usuario son añadidos a esta clase

  • ng-dirty los elementos con los que interactuó el usuario son añadidos a esta clase

  • ng-valid los elementos que son válidos son añadidos a esta clase

  • ng-invalid los elementos que no son válidos son añadidos a esta clase

                            
<div class="well">
    Message: {{message}}
    <div> Valid:
        <span class="summary" ng-class="myForm.$valid ? 'ng-valid' : 'ng-invalid'">{{myForm.$valid}}
        </span>
    </div>
</div>

                            
                        

Atributos de las Directivas

  • ng-model
  • ng-change
  • ng-minlength
  • ng-maxlength
  • ng-pattern
  • ng-required

Usando elementos input

  • ng-model
  • ng-change
  • ng-minlength
  • ng-maxlength
  • ng-pattern
  • ng-required
                            
<div id="todoPanel" class="panel" ng-controller="defaultCtrl">
    <form name="myForm" novalidate="">
        <div class="well">
            <div class="form-group">
                <label>Text:</label>
                <input name="sample" class="form-control" ng-model="inputValue" ng-required="requireValue" ng-minlength="3" ng-maxlength="10" ng-pattern="matchPattern">
            </div>
        </div>
        <div class="well">
            <p>Required Error: {{myForm.sample.$error.required}}</p>

            <p>Min Length Error: {{myForm.sample.$error.minlength}}</p>

            <p>Max Length Error: {{myForm.sample.$error.maxlength}}</p>

            <p>Pattern Error: {{myForm.sample.$error.pattern}}</p>

            <p>Element Valid: {{myForm.sample.$valid}}</p>
        </div>
    </form>
</div>
                            
                        

Usando elementos checkboxes

  • ng-model
  • ng-change
  • ng-true-value
  • ng-false-value
                            
<div id="todoPanel1" class="panel" ng-controller="defaultCtrl">
    <form name="myForm" novalidate="">
        <div class="well">
            <div class="checkbox">
                <label>
                    <input name="sample" type="checkbox" ng-model="inputValue" ng-true-value="Hurrah!" ng-false-value="Boo!">
                    This is a checkbox
                </label>
            </div>
        </div>
        <div class="well">
            <p>Model Value: {{inputValue}}</p>
        </div>
    </form>
</div>
                            
                        

Los atributos de los elementos textarea son los mismos que los del input

                            
<div class="form-group">
    <textarea name="sample" cols="40" rows="3" ng-model="textValue" ng-required="requireValue" ng-minlength="3" ng-maxlength="10" ng-pattern="matchPattern">    </textarea>
</div>
                            
                        

Usando los elementos select

                            
<div class="form-group">
    <label>Select an Action:</label>
    <select ng-model="selectValue" ng-options="item.action for item in todos">
    </select>
</div>
                            
                        

Se puede definir que valor vincular al modelo de la siguiente manera

                            
<select ng-model="selectValue" ng-options="item.id as item.action for item in todos">
    <option value="">(Pick One)</option>
</select>
                            
                        

Creando elementos optgroup

se utiliza para agrupar items basados en algun atributo

                            
<div class="well">
    <div class="form-group">
        <label>Select an Action:</label>
        <select ng-model="selectValue" ng-options="item.action group by item.place for item in todos">
            <option value="">(Pick One)</option>
        </select>
    </div>
</div>
<div class="well">
    <p>Selected: {{selectValue || 'None'}}</p>
</div>
                            
                        

Dependency Injection

Hay 3 maneras informar que componente inyectar

Implicitamente por el nombre de los parámetros de la función

                            
function MyController($scope, greeter) {
// ...
}
                            
                        

Usando la anotación propiedad $inject

                            
var MyController = function(renamed$scope, renamedGreeter) {
...
}
MyController['$inject'] = ['$scope', 'greeter'];
                            
                        

Usando la anotación de array en linea

Maneras informar que componente inyectar

                            
someModule.factory('greeter', ['$window', function(renamed$window) {
// ...
}]);
                            
                        

Donde se puede usar?

Factory Methods

                            
angular.module('myModule', [])
.factory('serviceId', ['depService', function(depService) {
...
}])
.directive('directiveName', ['depService', function(depService) {
...
}])
.filter('filterName', ['depService', function(depService) {
...
}]);
                            
                        

Module Methods

                            
angular.module('myModule', [])
.config(['depProvider', function(depProvider){
...
}])
.run(['depService', function(depService) {
...
}]);
                            
                        

Controllers

                            
someModule.controller('MyController', ['$scope', 'dep1', 'dep2', function($scope, dep1,
dep2) {
...
$scope.aMethod = function() {
...
}
...
}]);
                            
                        

Angular UI-Router

Provee una manera diferente de trabajar que ngRoute de AngularJS

Estados vs Ruta URL

Con los estados las vistas no estan acopladas a una URL y permite cambiar de vistas internamente sin la necesidad de cambiar la URL

Donde configurar los estados?

$stateProvider es el encargado de proveer de los estados en la aplicación y es configurado dentro del .config() del módulo

Ejemplo

                            
<!-- in index.html -->

<section ui-view="" class="future" style="top: -20px; display: none; "></section>

                            
                            
// in app-states.js (or whatever you want to name it)
$stateProvider.state('contacts', {
template: '<h1>My Contacts</h1>'
})
                            
                        

Donde se inserta la plantilla?

Cuando se activa un estado, la plantilla se inserta en el ui-view de su padre, si no lo tiene entonces se inserta en el index

Activando un estado

  • Llamando a $state.go()
  • Hacer click en un link con ui-sref
  • Navegar la URL asociada al estado

Configurando el template

  • template: html
  • templateUrl: page.html
  • templateUrl:function()
  • templateProvider: function()

Configurando el controllador

  • controller: function()
  • controller: 'MyCtrl'
  • controller: 'MyCtrl as contact'
  • controllerProvider: function()

Resolve

El controlador no se cargará hasta que no se hayan resuelto todas las dependencias

                            
$stateProvider.state('myState', {
  controller: function(){},
  resolve:{
    objetoSimple:function(){
      return {value:'asd'};
    },
    //Retorna un promise, es lo mas utilizado
    promiseObj:  function($http){
      return $http({method: 'GET', url: '/someUrl'});
    }
  }
}
                            
                        

Enviando Datos (se recomienda usar el 'data')

                            
$stateProvider
.state(contacts)
.state('contacts.list', {
templateUrl: 'contacts.list.html',
data: {
customData1: 44,
customData2: "red"
}
})
                            
                        

Eventos

Son disparados desde $rootScope

  • $stateChangeStart
  • $stateNotFound
  • $stateChangeSuccess
  • $stateChangeError
  • $viewContentLoading
  • $viewContentLoaded

Anidación de Estados

                            
$stateProvider
.state('contacts', {})
.state('contacts.list', {});
                            
                        

También se puede utilizar la propiedad 'parent' para anidar

Los hijos heredan las dependencias resueltas por su padre y los datos que hayan pasado, además si las vistas están anidadas los $scope se heredarán

Estado Abstracto

                            
$stateProvider
.state('contacts', {
abstract: true,
url: '/contacts',

// Note: abstract still needs a ui-view for its children to populate.
// You can simply add it inline here.
template: '<ui-view>'
})
.state('contacts.list', {
// url will become '/contacts/list'
url: '/list'
//...more
})
.state('contacts.detail', {
// url will become '/contacts/detail'
url: '/detail',
//...more
})
                            </ui-view>
                        

Multiples Vistas

                            
                                
<div ui-view="filters"></div>
<div ui-view="tabledata"></div>
<div ui-view="graph"></div>

                            
                        

Multiples Vistas

                            
$stateProvider
.state('report',{
views: {
'filters': {
templateUrl: 'report-filters.html',
controller: function($scope){ ... controller stuff just for filters view ... }
},
'tabledata': {
templateUrl: 'report-table.html',
controller: function($scope){ ... controller stuff just for tabledata view ... }
},
'graph': {
templateUrl: 'report-graph.html',
controller: function($scope){ ... controller stuff just for graph view ... }
},
}
})
                            
                        

Parámetros

Se recupera el valor pasado por medio de $stateParams

  • url: "/contacts/:contactId"
  • url: "/contacts/{contactId}"
  • url: "/contacts/{contactId:[0-9]{1,8}}"
  • url: "/contacts?myParam1&myParam2"
                            
$stateProvider.state('contacts.detail', {
url: '/contacts/:contactId',
controller: function($stateParams){
$stateParams.contactId
}
})
                            
                        

Ruta Absoluta

                            
$stateProvider
.state('contacts', {
url: '/contacts',
...
})
.state('contacts.list', {
url: '^/list',
...
});
                            
                        

Opciones para redireccionar

  • $urlRouterProvider.when('', '/index');
  • $urlRouterProvider.otherwise('/index');