CategoríaFRONTEND

ES6!

Si vas a hacer un proyecto nuevo  o simplemente vas a una entrevista como Javascript developer, hay puntos ES6 que deberías conocer.

Aunque no todos los aspectos de ES6 son soportados de forma nativa por los browser, sabemos que Babel, Typescript o Traceur  nos ayudan a ‘transpilar’ o convertir nuestro código de ES6 a ES5.

Usar frameworks como Angular 1x, Angular2, Emberjs , React , Aurelia o Vue con ES6 nos permite tener un código mantenible, desacoplado y testable.

ES6 incluye  módulos, Clases, Promises , Arrow Function, Interpolación, Default Paramenters y puedes ver mas detalles en http://es6-features.org/

Aquí solo brindo una pincelada rápida de los aspectos de ES6 que mas uso, para el proceso de transpiling usare JSPM y Babel , si no lo has configurado te recomiendo  “Manejo de módulos y Dependencias con JSPM“.

let y const

ES6 nos facilita el uso de let lo cual permite definir una variable para un scope especifico.

var lebron = 23
       if (true) {
           let lebron = "king";
           console.log(lebron); //king
       }
       console.log(lebron) //23

Ademas de let,  tenemos “const” para definir un valor constante que no varia cuando intentamos modificar su valor.

const CAVS = "winner"
CAVS = "losser"
console.log(CAVS)
//Resultado: Line 13: "cavs" is read-only

Arrow Functions =>

Es la forma corta de definir funciones en ES6,  si usamos “concise body” no es necesario usar el return para devolver el valor.

let WhoMVPGuy = (player) => player + " MVP"
console.log(WhoMVPGuy("lebron"))
// lebron MVP

Classes

Ya podemos crear clases con el keyword “class”  y utilizando this en el constructor podemos crear propiedades  o get para propiedades de solo lectura, ademas métodos  como MiMetodo() o métodos estáticos con “static”.

export class App {
    constructor() {
       console.log("hola");
       this.team = "cavs";
   }
    get CavsProperty() {
        return "Are you ready!!!"
   }
    ShowView() {
       const cavs = "winner";
       var lebron = 23;
       if (true) {
           let lebron = "king";
           console.log(lebron); //king
       }
       console.log(lebron) //23
       let WhoMVP = function(player) {
           return player + "MVP"
       }
       let WhoMVPGuy = (player) => player + " MVP
       console.log(WhoMVPGuy("lebron")
   }
   static GetPlayers() {
       console.log("Irving , Shumpper!")
   }
}

El keyword “extends” nos permite heredar de otra clase, “recordando llamar el método super()” en el constructor de clase hija, para iniciar el constructor de la clase padre.

export class Team {
   constructor() {
        this.team = "cavs";
   }
}
export class Player extends Team {
   constructor(number = 0) {
       super()
       this.number = number;
   }
}
let king = new Player(12)
console.log(king);
//Resultado: Player {team: "cavs", number: 12}

Interpolation

ES6 nos permite una forma fácil de interpolar valores en un string, usando `como delimitador y `${nuestravariable}  para renderizar.

let WhoMVPGuy = (player) => `Soy un el jugador ${player} el real MVP`
// Resultado: Soy un el jugador lebron el real MVP

For “of | in”

En el for podemos iterar con “of” ó “in”, con of lo realizamos  sobre el objeto.

let players = ['lebron', 'curry', 'durant'];
for (let player of players) {
    console.log(player);
}
//Resultado: lebron, curry, durant

Con “in” es sobre indices.

let players = ['lebron', 'curry', 'durant'];
for (let player in players) {
    console.log(player);
}
//Resultado: 0, 1, 2

Promises

ES6 tiene soporte nativo a las promises, las promesas es un objeto que espera a que una operación se complete y cuando finaliza esta puede enviar un “resolved o “rejected”.

El constructor de new Promise() acepta dos funciones como parámetros  ‘resolve’ y ‘reject’.

GetChampion(cavs, gsw) {
 const promise = new Promise(function(resolve, reject) {
 if (cavs > gsw) {
 resolve("cavs win")
 } else {
 reject(new Error('gsw win'))
 }
 })
 return promise
 }

Al devolver una promesa , el valor resuelto de la promesa se van pasando a las funciones asignadas o usando catch podemos tomar el error.

//usando la promesa
let cavs = 4
 let gsw = 3
 app.GetChampion(cavs, gsw).then(function(res) {
 console.log(res)
 }).catch(err => console.log(err))

//resultado: "cavs wins".

Nota: Recomiendo que mires el post de @carlosazaustre sobre manejar asincronía en js.
https://carlosazaustre.es/blog/manejando-la-asincronia-en-javascript/

Happy ES6!

Dependencias y Módulos con JSPM

El manejo de dependencias y la gestión de módulos en SPA es un tema que tiene diferentes actores en el mundo Javascript. Para la gestión de paquetes tenemos Bower, Nuget, NPM y JSPM y para la carga de módulos tenemos Browserify, Requirejs y Webpack, pero yo he decidido usar a nivel personal por NPM y JSPM

 JSPM es un gestor de paquetes igual que NPM , además de manejar dependencias , incluye carga de módulos mediante Systemjs que pueden estar definidos en Commonjs, AMD, además soporte de transpiler como Babel, Traceur o Typescript .

Explicaré como instalar JSPM, como utilizarlo para gestionar las dependencias , módulos y empaquetado de nuestro código.

Instalación y Configuración de JSPM

  1. Instalamos Nodejs
  2. instalamos JSPM mediante de NPM
npm install -g jspm

2- Iniciamos JSPM en el directorio de nuestro proyecto.

jspm init

4- Nos realizará varias preguntas para la configuración, para configurar como organizará los registros de los paquetes, directorios y transpiladores.

  •  Informa de la creación de Package.json
warn Running jspm globally, it is advisable to locally install jspm via npm inst
all jspm --save-dev.

Package.json file does not exist, create it? [yes]:
  • Deseas que los paquetes que se instalen mediante JSPM  y se registren en  package.json usen el prefijo jspm?
Would you like jspm to prefix the jspm package.json properties under jspm? [yes]
  • Cual directorio será la raíz para la aplicación o donde el servidor mostrará los archivos.
Enter server baseURL (public folder path) [./]:
  • Cual es el directorio de los paquetes de jspm
Enter jspm packages folder
  • En que directorio estará el config.js
Enter config file path [./config.js]:
  • La url de la aplicación o de donde el navegador cargara el directorio:
Enter client baseURL (public folder URL) [/]:
  • Si usaremos un transpiler  (Babel, Typescript o Traceur)
Do you wish to use a transpiler? [yes]:
Which ES6 transpiler would you like to use, Babel, TypeScript or Traceur? [babel]:

Al finalizar JSPM descargará las librerías necesarias para el module loader y transpiling.

ok Installed github:jspm/nodelibs-child_process@^0.1.0 (0.1.0)
ok Installed babel-runtime as npm:babel-runtime@^5.8.24 (5.8.38)
ok Installed core-js as npm:core-js@^1.1.4 (1.2.6)
ok Loader files downloaded successfully

Ya podemos mediante jspm instalar las librerías que usaremos en nuestra aplicación, en mi caso usare jquery y mustache.

Instalando paquetes mediante JSPM

JSPM nos permite instalar paquetes desde github o npm,  ahora instalamos Mustache y Jquery.

danyair:i18nexample dany$ jspm install mustache
     Updating registry cache...
     Looking up github:janl/mustache.js
     Downloading github:janl/mustache.js@2.2.1
ok   Installed mustache as github:janl/mustache.js@^2.2.1 (2.2.1)
ok   Install tree has no forks.

ok   Install complete.
danyair:i18nexample dany$

Escribiendo modulos con ES6 y JSPM

Ahora escribiremos una app simple utilizando las librerías descargadas mediante jspm (Mustache y Jquery) y escribiremos un modulo. En el directorio core.js y app.js utilizare la sintaxis de ES6 ya que tengo Babel para así utilizar clases y módulos.

core.js
Este modulo importa Mustache de ‘Mustache’ , creo la clase Core y en el constructor tenemos una propiedad, this.template en la que lee el template de Mustache.

La clase Core tiene un método ShowView que se encarga de pasar el viewmodel al template y renderizarlo con el método render de Mustache además de  exportar la clase Core para que pueda ser utilizada por otras.

import Mustache from 'mustache'
 export class Core {

constructor() {
 this.template = document.getElementById('mustachetemplate').innerHTML;

}

ShowView() {

var vm = {

myname: 'Dany Paredes',
 message: 'Using JSPM and Mustache!'
 }

document.getElementById('app').innerHTML = Mustache.render(this.template, vm);
 }

}

app.js

Este será el punto de entrada de la aplicación, importamos el modulo Core  y  $ de Jquery , creamos una instancia de Core y llamamos el método ShowView para visualizar la vista.

import {
 Core
 } from './core'

import $ from 'jquery'

$(document).ready(function() {

var core = new Core();

core.ShowView();

})

index.html:

Creamos el 2 div una para la view y otro que contendrá el template de Mustache.

 <div id="app">
 </div>

<script id="mustachetemplate" type="x-tmpl-mustache">
 <div class="row">
 <h1>{{myname}}</h1>
 <h2>{{message}}</h2>
 </div>

Incluimos system.js que nos permite cargar los módulos y config.js donde están definidas las dependencias de la app, con estas referencia ahora podemos definir que nuestro punto de entrara de app.

<script>
 System.import('app')
 </script>

Solo toca iniciar nuestra app con un webserver local, JSPM busca las librerías y dependencias de app.

Como eliminar la dependencia de config.js y system.js ?

JSPM nos permite optimizar el código con el uso de bundle y la creación de un sfx o (self execute), así evitamos tener
referencias a config.js y system.js

danyair: jspm bundle-sfx app
 Building the single-file sfx bundle for app...
 ok Built into build.js with source maps, unminified.

Comentamos las referencias a system, config , y comentamos el punto de entrada y agregamos la referencia a build.js

<!--<script src="jspm_packages/system.js"></script>
 <script src="config.js"></script>-->
 <!--<script> System.import('app') </script>-->

<script src="build.js"></script>

Descargar código:
https://github.com/danywalls/modulos-y-manejo-de-dependecias-con-jspm

Happy JSPM!.

Gracias a @oriolpuigbuil por el feedback!

Multi-idioma con Mustache y i18njs

Cuando hablamos de web multi-idioma en asp.net es un tema resuelto gracias a los resources, pero para una SPA en Javascript existen diferente soluciones.

En estos días varias personas me preguntaron cómo trabajaba el tema de idiomas en una SPA, mi respuesta es que a día de hoy uso i18n.js  la cual es una librería para soporte a i18n en javascript combinándola con una librería de template “mustache” o “handlebars”.

En este ejemplo crearé un formulario multi-idioma usando Mustache para la vista(view) , el cual mostrara el nombre y el apellido y  un select (combobox) donde se puede seleccionar el idioma para verlo en español, ingles o chino.

Primero descargar las librerias que necesito:

I18njs http://i18njs.com/js/i18n.js

Mustache  https://github.com/janl/mustache.js

JQuery https://jquery.com/download/

La estructura  será la siguiente:

langs: contiene los jsons con las traducciones. (en.json, es.js, ch.json).
libs: las librerias (jquery, i18n y mustache)
appweb.js el archivo que contendrá la lógica.
index.html: contiene la view y el template de mustache , además de un select para elegir el idioma.

index.html

Agrego   las librerías descargadas al index.html y creo el contenedor div “app” de la aplicación y el template de mustache, llamado “welcome” con las propiedades que quiero visualizar y llenar con el binding desde mustache.

Para saber mas sobre la sintaxis y templates de mustache. https://github.com/janl/mustache.js

<div id="app" class="container">
</div>
<script id="welcome" type="x-tmpl-mustache">
        <div class="row">
            <h1>{{appname}}</h1>
        </div>
        <p>{{picklang}}</p>
        <select id="slang">
            <option value="df">{{df}}</option>
            <option value="ch">{{chinesse}}</option>
            <option value="es">{{spanish}}</option>
            <option value="en">{{english}}</option>
        </select>
        <div class="row">
            <div class="col-xs-12">
                <p>{{name}} {{myname}}</p>
                <p>{{lastname}} {{mylastname}}</p>
            </div>
        </div>
    </script>

langs:

En el directorio Langs creo los jsons especificando los tags que se mostrarán en la vista (view).

es.json:

{
    "values": {
        "lastname": "Apellido",
        "name": "Nombre",
        "appname": "Aplicacion",
        "picklang": "Seleccione un Idioma",
        "english": "English",
        "spanish": "Espanol",
        "chinesse": "奇诺",
        "df": "Default"
    }
}

ch.json:

{
    "values": {
        "lastname": "姓",
        "name": "名称",
        "appname": "应用程序名称",
        "picklang": "选择一种语言",
        "english": "English",
        "spanish": "Español",
        "chinesse": "奇诺",
        "df": "Default"
    }
}

Repito el proceso para cada idioma de la aplicación.

appweb.js

Esta es la lógica de la aplicación, defino dos variables apptemplate y userlang.

apptemplate: Guarda la view de mustache.
userlang: Guarda el objeto de i18njs que contendrá las traducciones.

var apptemplate;
var userlang;

Creo la función NavigatorLanguage para detectar el idioma del navegador y especificar uno.

function NavigatorLanguage() {
    if (window.navigator.language != undefined)
        return window.navigator.language;
    else
        return es;
}

Luego usando jquery creo la función “GetES” que carga el json y la asigno a userlang  con el objeto de i18n.

function GetES(callback) {
    $.ajax('langs/es.json').done(function(text) {
        userlang = i18n.create(text);
        callback(true)
    })
}

Creo el método RenderView que se encarga de renderizar la view de Mustache, recibiendo por parametro el template y el viewmodel e internamente llamando el método Mustache.render para actualizar la vista.

function RenderView(template, vm) {
    return Mustache.render(template, vm);
}

Para enviar los datos a la view creo el método bindview() en el cual enviare el viewmodel (json) que espera el método RenderView junto al template.

function bindview(vm) {

    var vm = {
        name: userlang("name"),
        myname: "Dany",
        lastname: userlang("lastname"),
        mylastname: "Paredes",
        appname: userlang("appname"),
        picklang: userlang("picklang"),
        english: userlang("english"),
        spanish: userlang("spanish"),
        chinesse: userlang("chinesse"),
        df: userlang("df")
    }

    document.getElementById('app').innerHTML = RenderView(apptemplate, vm);
}

Ahora toca el proceso de saber el lenguaje del usuario y a partir de ahí cargar el json, llamar los métodos de binding y render de la view.

function showview(lang) {
    console.log(lang)
    apptemplate = document.getElementById('welcome').innerHTML;
    var lang = lang || NavigatorLanguage();
    switch (lang) {
        case "es":
            GetES(bindview);
            break;
        case "en":
            GetEN(bindview);
            break;
        case "ch":
            GetCH(bindview);
            break;
        default:
            GetEN(bindview);
    }
}

En el función document.ready() registramos el evento para cuando el usuario cambie el lenguaje y tomar el idioma s seleccionado para enviarlo a la  función showview.

$(document).ready(function() {
 $(document.body).on('change', '#slang', function() {
         showview(this.value)
     });
     showview()
})

Código de ejemplo https://github.com/danywalls/multi-idioma-con-i18njs-y-mustache

Demo  http://i18mustacheejemplo.surge.sh/ 

Gracias a @oriolpuigbuil por el feedback!

Imagen  by Freepik

Happy i18n!

SPA en 2016 ?

Primeramente, recomiendo como lectura obligatoria la presentación de @CKgrafico sobre la evolución de desarrollo frontend.

Estamos en 2016, el desarrollo de SPA ha cambiado mucho con relación a sus inicios, los actores como jquery, knockout, mootools han quedado un poco limitados con los requerimientos del desarrollo actual.

El mercado actual nos brinda un sin número de Frameworks y tecnologías para el desarrollo de frontend.

Al momento de seleccionar un Framework para nuestra SPA tenemos que asegurarnos que este nos brinde los aspectos necesarios para el desarrollo, como es la creación de components, routing, data binding, templates, models, services, DI, testing etc.

Este framework debe permitirnos desarrollar nuestra SPA en capas tomando en cuenta la responsabilidad de cada una de ellas.

La vista(view) debe estar conformada solo de html / css y su rol es únicamente definir la estructura e interfaz de usuario, este framework debe brindarnos la capacidad de tener soporte para templates o apoyarse en alguna librería como handlebars o mustache.

El framework debe permitirnos tener clases que representen controllers y manejen el envío de datos dinámicos a la vista(view) e interactuar con los elementos, además de tener clases que representen los servicios para encapsular los métodos de acceso a las api, entre los diferentes componentes de nuestra aplicación.

Al desarrollar debemos apostar por HTML5, ES6 y CSS3 para poder tener muchos problemas resueltos y no tener que reinventar la rueda.

HTML5

Nos brinda un sin número de opciones en el browser del cliente y hacer que nuestra aplicación entre estas tenga soporte a Canvas, Geolocation , Video, IndexDB, LocalStorage y SessionStorage.

https://developer.mozilla.org/es/docs/HTML/HTML5

ES6

Esta versión de Javascript a diferencia de ES5 nos permite tener módulos, classes , promesas, templates de forma nativa en Javascript y más opciones.

https://github.com/lukehoban/es6features#readme

Nota: No todas las bondades de ES6 son soportadas por los browsers, pero podemos utilizar transpilers y polyfills los cuales compilan nuestro código de ES6 a ES5 y  a la vez ser soportado por los browsers.

CSS3

Los estilos son un aspecto importante y es vital basarnos en css3 para poder tener soporte a Media Queries, Colores, Selectores de 3 nivel, Animaciones.

http://www.w3schools.com/css/css3_intro.asp

Pero qué herramientas necesito?

Un Editor moderno,Nodejs (Transpiler/Polyfills) ,Package Manager (Bower, Nuget, NPM, JSPM) y apostar por un Framework Javascript (Angular, React, Ember, Aurelia etc.)

Editores o IDE

Este es un aspecto importante ya que necesitamos que un IDE o Editor nos facilite el refactor, autocompletado, soporte de plugins para frameworks o librerías al día de hoy y los que puedo recomendar son:

WebStorm https://www.jetbrains.com/webstorm/

Visual Studio Code https://code.visualstudio.com

SublimeText 3 https://www.sublimetext.com/3

VS2015: https://www.visualstudio.com

Emacs:  https://www.gnu.org/software/emacs/

Gracias a Juanma  por recordarme a Emacs, es un editor al que hay que dedicarle su tiempo a aprenderlo.


Guia básica de Emacs: http://www.braveclojure.com/basic-emacs/

Configuraciones ya listas para Javascript en Emacs

@gulnor https://github.com/jmhdez/emacs.d/blob/master/lang/javascript.el

Yo uso Visual Studio Code

Package Manager

Un Package manager se encarga de facilitarnos el proceso de registro, descarga y dependencias de librerías de que usamos en nuestra aplicación.

Existen diferentes gestores de paquetes:

Nuget: https://www.nuget.org/

Bower: https://bower.io/

NPM: https://www.npmjs.com/

JSPM: http://jspm.io/

Yo uso NPM y JSPM.

Transpiladores

Los transpiladores nos permiten usar las bondades de ES6 o ES7 al día de hoy y convertirlas a ES5, además que mediante polyfills podemos darle soporte en los navegadores.

Al día de hoy contamos con los siguientes:

Babel: https://babeljs.io/

Typescript: https://www.typescriptlang.org/

Traceur: https://github.com/google/traceur-compiler

Yo a nivel personal inicie con Typescript debido a que estaba realizando ciertas cosas con Angular 2, pero al día de hoy estoy replanteando seriamente usar Babel.

Frameworks

Aquí existe un mercado increíble de opciones en la cual cada una tiene sus ventajas y su forma especial, sería bueno que mires algunos y te quedes con el que más te gusta.

https://angular.io/ Google

http://emberjs.com/ by Yehuda Katz

https://facebook.github.io/react/ Facebook

http://aurelia.io Aurelia

Ahora solo toca tomar lo que nos más nos guste y desarrollar SPA pensando en el 2016.

Happy SPA!

Imagen Designed by Freepik

Crea y Organiza Tests con Jasmine

Uno de los puntos quizás más complejos en Jasmine ,es la forma de organizar los tests, Jasmine nos permite mucha flexibilidad a la hora de organizar nuestros tests, aunque por defecto Jasmine provee una estructura, podemos definir la nuestra basado a nuestra necesidades, en mi caso utilizo la siguiente:

NbaFinalsApp
 /modules
      teams/team.js
      players/players.js
 /tests
      teams/team.spec.js
      players/players.spec.js
 SpecRunner.html
          ...

En este ejemplo tenemos 1 SpecRunner para todo el proyecto, pero puede ser un SpecRunner por modulos.

Con la estructura definida a nivel de ficheros y directorios, nos falta organizarlos dentro de Jasmine.

En Jasmine los test se organizan usando describe, ya que nos permite agrupar los test en secciones y anidarlos.

Ejemplo:

describe("NBA Finals",function(){
   describe('si Lebron anota 40', function(){
    });
    describe('si Irving anota 40', function(){
    });
})

Para escribir test con Jasmine es fácil, primero la función  “describe” y luego nos apoyamos en las diferentes  funciones que nos provee el framework.

Entre las funciones tenemos, it() que es contenedor de unit test, la cual podemos anidar con la función describe además tenemos beforeEach y afterEach nos sirven para configurar y preparar configuraciones de los test y los Matchers para verificar o validar el resultado.

Jasmine tiene un sin número de Matchers para realizar comparaciones en nuestros tests, entre los Matchers que contiene listare algunos:

expext(obj).toEqual(otherobj) para comparar objetos.
expect(obj).toBe(otherobj); utiliza ===
expect(obj).toMatch(regularexpresion): Compara a partir de una expresion regular.
expect(object).toBeDefined()

Si deseas ver la lista completa puede ir a la documentacion oficial http://jasmine.github.io/2.0/introduction.html

Pero también nos permite crear nuestro propios Matcher, en mi ejemplo quiero verificar si es el número 23.

Para crear un Matcher propio debemos realizarlo en la función beforeEach() y utilizando la función this.addMatchers() y podemos agregar un mensaje al error.

La función addMatchers, contiene la función “compare” retorna un objeto result  que en la propiedad pass podemos asignar el resultado de nuestra verificacion retornando un boolean ademas y  en propiedad message asignar el resultado del test.

Más informacion: http://jasmine.github.io/edge/custom_matcher.html

Pero veamos todo esto en la práctica.

Con describe defino el test,  usando beforeEach defino las variables para el test, jasmine.addMatcher creo Matcher “IsKing” que verifica si el jugador tiene el número 23, con it defino las pruebas unitarias donde usare los diferentes Matchers de Jasmine y el Matcher “IsKing”.

Si quieren ver todo en funcionamiento puede bajar el proyecto de ejemplo el cual contiene las clases a las cuales hago referencia en el test y explicada en el inicio.

describe("NBA Finals", function () {
   var lebron;
   var irving;
   beforeEach(function () {
       lebron = new Player("lebron", "", 0, true);
       irving = new Player("Irving", "1", false);
       jasmine.addMatchers({
           IsKing: function () {
               return {
                   compare: function (playernumber) {
                      var result = { pass: playernumber === 23 };
                       if (result.pass) {
                           result.message = "Si es 23";
                       } else {
                           result.message = "No es 23 es " + playernumber;
                       }
                       return result;
                   }
               }
           }
       });
   });
    describe('Cavs', function () {
       it("Lebron esta cancha", function () {
           expect(lebron).toBeDefined();
       });
       it("Es el numero 23", function () {
           expect(irving.playernumber).IsKing();
       })
       it("Tiene el balon", function () {
           expect(lebron.containsballon).toBe(true);
       });
   });
})

Si corremos el Test en el browser veremos que falla ya que estamos pasando el jugador irving en el test del numero 23.

Jasmine

Ahora solo  pasar el objeto lebron y nuestros test pasara sin problemas.

Jasmine

Para más información la documentación oficial:
http://jasmine.github.io/edge/custom_matcher.html

Descargar el código:
https://github.com/danywalls/organizando-con-jasmine

Hola Jasmine

En estos días me he visto en la necesidad de adoptar un framework de testing para una aplicación web, de todos los diferentes framework que hay en el mercado de Javascript he optado por mirar Jasmine.

Jasmine es uno de los frameworks más utilizados para realizar pruebas unitarias, se basa en Behavior Driven Development y permite realizar test tanto en el cliente como en el servidor.

Para trabajar con Jasmine inicialmente podemos utilizar la versión standaralone que es un .zip, listo para trabajar y lo puedes descargar en https://github.com/jasmine/jasmine/releases ,al descomprimir nos encontramos con los siguientes archivos:

Screen Shot 2016-06-16 at 20.05.00

Lib : Contiene la librería de Jasmine y los archivos necesarios para su ejecución.
Spec: En BDD los test son llamados specs y en el directorio spec están nuestros tests de ejemplo.
Src: Contiene archivos javascript relacionados con el test ejemplo, ahí puede estar nuestro api.js o clientes.js.

Si abrimos el archivo SpecRunner.html vemos que está organizado inicialmente el css  y las librerías de Jasmine y luego los Spec (Test) y finalizando  los archivos fuentes.

Pero en nuestro caso vamos a crear nuestro propio SpecRunner, del directorio lib he tomado lo siguientes archivos y lo he copiado en un directorio “DanyJasmineSetup”.

– jasmine.css
– jasmine.js
– jasmine-html.js
– boot.js
– SpecRunner.html

Creamos nuestro test CavsSpec.js y modifico SpecRunner.html para incluya nuestro nuevo test,  CavsSpec.js

Screen Shot 2016-06-16 at 21.24.48

Ahora en Nba.Spec.js escribo un test simple, it define el test, expect verifica y utilizamos el matcher ‘toBeTruthy’ el cual realiza la comparación si el object que recibe expect es verdadero, en este post no entraré en detalles sobre la sintaxis, solo explico lo rápido que es configurar nuestro entorno de test con Jasmine.

describe("NBA Finals",function(){
 it("Ganaran los cavs ",function(){
 expect(true).toBeTruthy();
 })
})

Al abrir nuestro SpecRunner.html  nos muestra que un nuestro test “Ganaran los Cavs” se cumple.

Screen Shot 2016-06-16 at 21.28.40

Como podemos ver que fácil es montar nuestro entorno de test con Jasmine. 

Para mas información la documentación oficial:

http://jasmine.github.io/edge/introduction.html

Descargar el código:

https://github.com/danywalls/hola-jasmine

Event Binding con Angular2

Cuando creamos aplicaciones con Angular2  una de las tareas comunes es tomar los eventos del DOM, cuando el usuario realiza un click, pasa el mouse por un elemento etc, para lograr esto usamos Event Binds que nos permite responder a cualquier evento del DOM.

En este ejemplo muestro cómo vincular eventos del DOM con elementos, para seguir los pasos te puedes guiar del proyecto “Ejemplos con Angular2” .

Manos a la obra, al igual que el artículo de Class y Style Binding con Angular2 para realizar el Event Binding decoramos nuestro elementos de html con ()  y dentro especificamos el evento como  ‘mouseover’  , ‘click’ o cualquiera de los eventos disponibles  en este caso los el evento ‘mouseover’ y ‘click’ los suscribimos  a las funciones “CleanFriends” y “GetFriends”.

Primero modificamos el template del componente peppig.component.ts.

<a (mouseover) = "CleanFriends()"  class="waves-effect waves-light btn" [class.disabled] = "isdisabled" >
<a (click)="GetFriends()" class="waves-effect waves-light btn">Get Friends</a>

Hemos vinculado los eventos del DOM mouseover y click , utilizando el paréntesis ()  y para la suscripción a la función el  =”nombre de la función”  en este caso GetFriends()  que llamará el servicio PeppaPigService el cual se encargará de llenar nuestro array this.friends  y CleanFriends()  que vacia el array.

 CleanFriends() {
    this.friends = [];
    console.log(this.friends);
 }

 GetFriends() {
 this.friends = this._peppapigService.getPeppaFriends();
 console.log(this.friends);
 }

Para visualizar los elementos de array y ver cómo se eliminan vamos usar una ul y la directiva *ngFor.

<ul class="collection" >
 <li *ngFor="let f of friends">
 <a class="collection-item">{{f}}</a> 
 </li>
 </ul>>

Guardamos los cambios y escribiendo npm start en el directorio de la aplicación, iniciamos la transpilacion y el webserver.

Angular2 NPM Start

Angular2 NPM Start

Ahora accedemos a http://localhost:3000 y  hacemos click en “get friends”  el cual lanza el evento click y llama al servicio que a su vez llenará el array y mostrará el listado de amigos.

Al pasar el mouse por “clean friends” dispara el evento “mouseover”, vacia el array y el listado desaparece.

click

En muchos casos necesitamos saber el elemento que lanzó el evento, para realizar esto  le agregamos el parámetro $event en al función y en template, ahora al lanzar el evento “mouseover”, nos muestra toda la informacion con relacion al elemento que lanzo el evento.

Screen Shot 2016-06-06 at 10.35.12 PM

MouseOver , Event

Todos los eventos del DOM se lanzan en el orden de su árbol en el DOM, causando el “Event Bubble”, imaginemos que nuestro div está suscrito a un evento click y a una función específica.

 <div (click)="ClickContenedor()" ... 
//codigo resumido por omision.
ClickContenedor(){
 console.log("click contenedor");
 }

Ha hacer click en “GetFriends()” se dispara el DOM propaga el evento y también se lanza el evento Click de Div, como detenemos esto ?

Nos recordamos de event.stopPropagation() de jquery ?  pues solo tenemos que ir a nuestro evento y llamar el método $event.stopPropagation().

CleanFriends($event) {
 $event.stopPropagation()
 console.log(event);
 this.friends = [];
 }

Para mas informacion la documentacion oficial:

https://angular.io/docs/ts/latest/guide/template-syntax.html#!#event-binding

Descargar el código:

https://github.com/danywalls/components-con-angular2

Happy Angular!

Class Style binding con Angular2

Angular2 nos facilita agregar clases y modificar el estilos de los elementos en nuestros components mediante [class] y [style] binding.

Para este ejemplo usare materializecss  que permite asignar estilos a la aplicación y de paso tenga mejor look. Si no has usado materializecss no importa, lo importante de todo esto es que puedas modificar el aspecto visual de un elemento a partir de alguna lógica o estado de una propiedad del componente.

En el ejemplo modificar el template del componente peppapig.component.ts y agrego <a con las clases de materialize con css de materialize para darle un aspecto de tipo button y dependiendo de la propiedad “isdisabled” jugar a agregar o quitar la clase css.

 <a class="waves-effect waves-light btn">button</a>

[Class] binding:

Nos permite agregar una clase css en este ejemplo a partir de una condicion boolean, se agrega la clase “disabled” la sintaxis resultante:

[class.disabled] = “isdisabled”.

Seguir leyendo

Property Binding e Interpolation con Angular2

Interpolation es la forma más conocida para binding de datos en angular, este ha cambiado pero el proceso internamente continúa igual. Angular2 compila nuestro template, crea un elemento en el DOM, haciendo referencia a la propiedad de nuestro componente.

Para este ejemplo modificaremos el componente peppapig.component.ts y creamos una propiedad welcome, la incluiremos en el template y utilizo {{}}, [] y bind- para mostrar la propiedad de diferentes formas pero con el mismo resultado:

@Component({
 selector:'peppapig-component',
 template:`
 <div>
 <h2>{{welcome}}</h2>
 <h2 [textContent]="welcome"></h2>
 <h2 bind-textContent="welcome"></h2>
 </div>`,
 providers: [PeppaPigService]
})
export class PeppaPigComponent{
 
 friends: string[];
 welcome: string = "Peppa Pig Friends"
 
 constructor(private _peppapigService: PeppaPigService){
 
 this.friends = this._peppapigService.getPeppaFriends();
 console.log(this.friends);
 }
}

Que ha pasado ?

Si abrimos el browser y vemos que se ha mostrado la propiedad 3 veces, aunque hemos accedido a ella de diferentes formas:

<h2>{{welcome}}</h2>
 <h2 [textContent]="welcome"></h2>
 <h2 bind-textContent="welcome"></h2>

{{}}

En la primera línea utilizamos {{}}  en la se especifica dentro {{}} la propiedad y lo utilizamos dentro de un tag del DOM, a nivel de lectura del código es más agradable.

[]  bind-

Al igual que punto anterior en este especifico con bind- la propiedad que quiero acceder de este elemento del DOM, para realizar el binding.

En el caso 2 y 3 no se usa  el elemento del DOM directamente, sino se accede a la propiedad que expone.

Tanto 1,2,3  son válidas porque todas angular2 realiza el binding.

Entonces cual usar y cuando ?

Es una cuestión de lectura y gusto, ambas opciones son válidas pero en mi caso prefiero usar {{}}  cuando solo necesito representar un texto aprovechando directamente el elemento del DOM  Ejemplo:

<h1>{{title}}<h1>

[] o bind-element cuando necesito interactuar con una propiedad del elemento, ejemplo:

<img bind-src="mipropiedaddelcomponent">

Hay que recordar que esta forma de acceder a propiedades del componente es 1 way binding, esto quiere decir que si la propiedad cambia en el componente, esta la refleja en el DOM pero no de viceversa.

Si deseas bajar el ejemplo:

https://github.com/danywalls/components-con-angular2

Saber mas sobre Interpolation:

https://angular.io/docs/ts/latest/guide/template-syntax.html#!#interpolation

Gracias a @oriolpuigbuil por el feedback.

 

Creando Servicios con Angular2

Los Services en Angular2 nos permite exponer una funcionalidad a nuestro componente, como traer información de un servidor, exponer una configuración o alguna lógica de negocio que no esté vinculada directamente con la view.

En Angular2 al igual que los componentes , los Services son una clase. en este ejemplo utilizare angular-seed y vamos a crear un  servicio y lo inyectamos a un componente, si no sabes como crear un componente puede puedes leer el post anterior donde explico “Components con Angular2.”

Si deseas puedes descargar  el ejemplo anterior y en el directorio app/services/creamos un fichero peppapig.services.ts, este sera nuestro servicio y se encargará de  retornar un array con un listado de nombres a nuestro componente.

export class PeppaPigService {
 
 getPeppaFriends(): string[] {
 return ["pedro poni","madamme gazelle", "dani dog"]
 }
}

Como utilizo mi services en mi componente?

Primero hacemos una referencia de PeppaPigService a nuestro componente peppapig.component.ts.

import {PeppaPigService} from '../services/peppapig.services';

Agregando este parámetro en el constructor tenemos una referencia a PeppaPig Service

   constructor(private _peppapigService: PeppaPigService){

}

El trabajo de  la inyección de  dependencias es “Inyectar las dependencias de las clase cuando se crea”,  en resumen cuando se iniciemos la clase “peppapigComponent” , Angular mira en el constructor y detecta que necesita un “PeppaPigService” por tanto crea una instancia de peppapigService y la inyecta en la clase.

Providers:

Ahora tenemos que especificarle a PeppaPigComponent  como crear PeppaPigService, en el atributo @Component agregamos una nueva propiedad Providers el cual acepta un array de tipo “any”, aqui agregamos nuestro servicio[ PeppaPigService ].

@Component({
 selector:'peppapig-component',
 template:'<h1> Soy La peppa pig</h1>',
 providers: [PeppaPigService]
})

Consumiendo nuestro servicio ?


Creamos una propiedad  “friends” de tipo array de string , en el constructor llamaremos nuestra referencia de peppaPigService y le indicamos que llene nuestra propiedad friends, para visualizar que el array muestra los datos en el console.log mostraremos el array.

export class PeppaPigComponent{
 
 friends: string[];
 constructor(private _peppapigService: PeppaPigService){
 
 this.friends = this._peppapigService.getPeppaFriends();
 console.log(this.friends);
 }
}

services

Para descargar el codigo de ejemplo https://github.com/danywalls/ejemplos-con-angular2.

Happy Angular2

© 2017 Danywalls

Tema por Anders NorénSubir ↑