A 5 days introduction to pure javascript programming and Angular for beginners. Slides are in Italian language. Including a lot of code, some exercise and guide for "tour of heroes"
2. DAY ONE - JAVASCRIPT HISTORY
JS é stato creato nel 1995 da Brendan Eich, un programmatore della Netscape.
Principalmente per sopperire all' assenza di un linguaggio che potesse interagire con i
browser e permettere di automatizzare i processi.
Successivamente In parallelo vennero sviluppati altri tentativi sullo stesso piano come JScript
e (dopo) ActionScript della Macromedia (di cui fece parte anche Einch) fino alla nascita della
specifica di Jesse James Garrett che rivoluzionó JS definendo un set di tecnologie che
facessero da spina dorsale per le future implementazioni del linguaggio e portó all' avvento di
AJAX . Da quel punto in poi la community é stata molto attiva producendo migliaia di librerie
tra cui Jquery, Prototype e Dojo.
Si istituirono altre fondazioni open source che avevano come obiettivo quello di sviluppare
una libreria standard per lo sviluppo su javascript fuori dal contesto del browser da cui
nacque Node.js
3. DAY ONE - JAVASCRIPT HISTORY
1995: At Netscape, programmer Brendan Eich created "JavaScript".
1996: Microsoft releases "JScript", a port for IE3.
1997: JavaScript was standardized in the "ECMAScript" spec.
2005: "AJAX" was coined and the web 2.0 age begins.
2006: jQuery 1.0 was released.
2010: Node.JS was released.
2015: ECMAScript 6 was released.
4. DAY ONE - VARIABILI
Variabili
Le variabili sono "contenitori di dati" generici (non tipizzati)
Dichiarazione: var, let or const (since ES6)
Scope: Global, Local (aka Function Scope)
Data Types
Variabili implicite: this, arguments [window e console (solo su client)]
5. DAY ONE - VARIABILI
Tipi di dati
null var x = null;
undefined var x;
Number var x = 1; var y = new Number(1);
Boolean var x = false; var y = new Boolean(expression)
String var x = "John"; var y = new String("Jack");
Date var x = new Date(2018, 1, 1, 10, 33, 30); var y = new Date(milliseconds)
Array var x = ["el1", "el2"]; var y = new Array();
Object var x = {firstName: "John", lastName: "Doe"}; var y= new Boolean();
Regexp var x = /ab+c/; var y = new RegExp("ab+c");
Function var x = function(a, b) {return a+b;}
var y = new Function("a", "b",
"return a+b;");
Symbol var x = Symbol();
6. DAY ONE - VARIABILI
Hoisting: Declare Your Variables on top
“Thanks to the Hoisting a variable can be used before it
has been declared. (except let and const variables)”
x = 5; //assignment
doSomethingWithX(x); //using variable before initialization
var x; //declaration
Lo stesso vale per le funzioni
7. DAY ONE - VARIABILI
One statement, many variables
var a, b, c=1; // a e b sono undefined, c é uguale a 1
var a=b=c=1; // a, b e c valgono 1;
Ridichiarazione
var a = 1;
var a;
console.log(a); // a vale ancora 1;
Migrazione da var (old ES versions) a let/const
var a = 1; // vecchia sintassi
let a = 1; // variabili che possono mutare il valore dopo la dichiarazione
const a = 1; // variabili che non possono mutare il proprio valore dopo la dichiarazione
8. DAY ONE - VARIABILI
Type Coercion
“Type coercion is the process of converting value from
one type to another (such as string to number, object to
boolean, and so on). Any type, be it primitive or an
object, is a valid subject for type coercion. To recall,
primitives are: number, string, boolean, null, undefined +
Symbol (added in ES6).”
10. DAY ONE - OPERATORS
Gli operatori sono simboli che permettono di assegnare, comparare e modificare
valori in una variabile o condizione
Si suddividono in Assignment, Conditional, Logical, Bitwise
Altri operatori speciali:
- delete,
- typeof,
- instanceof
- in (usato nei loop for)
- void
11. DAY ONE - OPERATORS
Operatori Aritmetici (e non)
Simbolo Descrizione
= Assegnazione variabile
+
Addizione numerica/Concatenazione stringhe o oggetti/Unario più (tenta
la conversione in numerico dell' oggetto)
* Moltiplicazione
/ Divisione
% Resto
--
Assegnazione e decremento (di variabile)
++ Assegnazione e incremento (di variabile)
12. DAY ONE - OPERATORS
Operatori comparativi
Logical operators implement lazy evaluation
Gli operatori sono pressoché identici (==, !=, >, <, >=, <=, &&, ||) a quelli Java con la
differenza tra strict/loose comparison
0==''; //loose comparison, returns true
0===''; //strict comparison, returns false
Nonostante la strict comparison si possono commettere errori
true + true === 2 //true
true === 1 // false (hopefully)
13. DAY ONE - OPERATORS
Operatori comparativi
Operatore Ternario
( condition ) ? then : else
var message = age > 18 ? "Adult" : "Too young";
a differenza di Java, posso eseguire un ternario senza assegnazione
age > 18 ? doThis() : doThat();
14. DAY ONE - DATA TYPES
Data types
Le strutture di dati sono il building block per le tipologie di oggetti definibili nelle
variabili
Primitivi (immutabili): null, undefined, string, Boolean, number, Symbol
Oggetti (referenced): Date, Array, Object, Function
15. DAY ONE - DATA TYPES
Numbers e Aritmetica
I numeri includono particolari numeri speciali
Positive infinity -> Number.POSITIVE_INFINITY
Negative infinity ->Number.NEGATIVE_INFINITY
NaN (not a number)
Il numero massimo di decimale é 17, e l' aritmetica sui numeri a virgola mobile non é accuratissima!
var x = 0.1+0.2; // x will be 0.30000000000000004, what a mess!!
var x = ((0.1*10)+(0.2*10))/10; // x now will be 0.3
Don't mess with mixed data types
console.log(1+2+3) --> 6
console.log("5"+2+3) --> 523
console.log(2+3+"5") --> 55
16. DAY ONE - DATA TYPES
Numbers e Aritmetica - Math
Math é un oggetto implicito di utility per svolgere operazioni aritmetiche. Contiene
fondamentali metodi e costanti per il calcolo, qualche esempio:
Math.PI pigreco
Math.abs(n) valore assoluto di un numero
Math.pow(n, p) potenza di p di un numero n
Math.min(n, n1..nx)/Math.max(n,n1..., nx) ritorna il numero maggiore/minore tra i
parametri in ingresso
.... e molto altro (random, round, sin, acos)
17. DAY ONE - DATA TYPES
Strings
Le stringhe sono variabili primitive (single/double quoted), tuttavia possiedono diversi metodi e
proprietá e funzioni tra cui:
length ritorna la lunghezza della stringa
indexOf ritorna l' indice numerico della prima occorrenza di un testo specifico all' interno di una
stringa
slice/substring/substr seppure con sottili differenze tutte e tre tagliano una stringa dati i due
estremi posizionali
replace sostituisce le occorrenze di un testo specifico (o regexp) con un altro testo
toUpperCase/LowerCase il nome dice tutto
Honorable mentions: charAt, trim, concat e molto altro!
18. DAY ONE - DATA TYPES
Objects
Gli oggetti sono normalmente definiti come literals i cui valori vengono espressi
come mappa chiave:valore:
let car = {
name: "Saturn", // a property containing a string
getCar: function() {...}, // a property containing a function
nestedCar: { // a property containing a nested object
nestedName: "nestedValue"
}
}
per accedere alla property nestedName si segue il path dell' oggetto
car.nestedCar.nestedName oppure car["nestedCar"]["nestedName"]
19. DAY ONE - DATA TYPES
Objects - Metodi del costruttore Object
Object, oltre ad essere istanziabile (creando un nuovo oggetto) puó essere
utilizzato attraverso i metodi del costruttore (senza istanza) che contengono
funzioni fondamentali nello sviluppo, di seguito i metodi piú utilizzati nello sviluppo:
Object.create(obj) ritorna un nuovo oggetto dal prototipo di obj
Object.keys(obj) ritorna un array contenente le property names di obj
Object.assign(obj): ritorna un nuovo oggetto copiando tutte le prop di obj
altri metodi sperimentali e non come Object.is, Object.freeze, Object.observe
20. DAY ONE - DATA TYPES
Dates
Gli oggetti Date rappresentano un singolo momento nel tempo
Costruzione di una istanza dell' oggetto
new Date(); //date based on client system settings current time (with TZ)
new Date(value); //current time in millis
new Date(dateString); //try parsing a date from a string
new Date(year, monthIndex [, day [, hours [, minutes [, seconds [, milliseconds]]]]]); //using single fields,
omitted ones are setted by default to 0
//date valide
var today = new Date();
var birthday = new Date('December 17, 1995 03:24:00');
var birthday = new Date('1995-12-17T03:24:00');
var birthday = new Date(1995, 11, 17);
var birthday = new Date(1995, 11, 17, 3, 24, 0);
21. DAY ONE - DATA TYPES
Dates - Formattazione
toString: il metodo di default formatta la data in base al locale impostato sulle
impostazioni del sistema del client
Sun Sep 16 2018 16:00:43 GMT+0200 (Central European Summer Time)
toLocaleDateString fornisce una variante con cui visualizzare una data in base al
locale e la timezone
console.log(event.toLocaleString('en-GB', { timeZone: 'UTC' }));
20/12/2012, 03:00:00
Non é possibile specificare un date format pattern nativamente, per questo ed altri
motivi si utilizzano librerie specifiche per la manipolazione e formattazione di date
(moment)
22. DAY ONE - DATA TYPES
Dates - Getters e setters
É possible recuperare e impostare i singoli valori di una data attraverso funzioni getter & setter.
getFullYear()/setFullYear(n) //anno (locale) 4 digits
getMonth()/setMonth(n) 0-11
getDate()/setDate(n) //giorno del mese - 1-31
getDay()/setDay(n) //giorno della settimana -0-6
getHours()/setHours(n) //ora locale 0-23
getMinutes()/setMinutes(n) //minuti 0-59
getSeconds()/setSeconds(n) //secondi 0-59
getMilliseconds()/setMilliseconds(n) //millis 0-999
getTime()/setTime(n) //millisecondi dal 1 gennaio 1970
per la lista completa consultare
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date
23. DAY ONE - DATA TYPES
Arrays
Un array é una lista di oggetti a cui é possibile accedere tramite un indice
let fruits = ["Apple", "Banana", "Orange"];
console.log(fruits[1]); // prints Banana
24. DAY ONE - DATA TYPES
Arrays
Per aggiunta/rimozione di valori:
push aggiunge uno o piú elementi in coda all'array
fruits.push("Watermelon"); //fruits contains ["Apple", "Banana", "Orange", "Watermelon"]
pop rimuove l'ultimo elemento dalla coda dell'array (ritorna l' elemento stesso)
fruits.pop(); //fruits contains ["Apple", "Banana"]
shift rimuove il primo elemento dalla testa dell' array (ritorna l' elemento stesso)
fruits.shift(); //fruits contains ["Banana", "Orange"]
unshift aggiunge uno o piú elementi dalla testa dell' array
fruits.unshift("Watermelon"); //fruits contains ["Watermelon", "Apple", "Banana", "Orange"]
25. DAY ONE - DATA TYPES
Arrays
per alterare il valore di un elemento esistente é sufficiente assegnarlo tramite indice
fruits[1] = "Pear"; // fruits contains ["Apple", "Pear", "Orange"];
Altri metodi fondamentali:
join(separator): converte l' array in una stringa con valori separati da separator
fruits.join(" * ");// "Apple * Banana * Orange"
splice(idx, nElem) ritorna un nuovo array rimuovendo nElem elementi iniziando da idx
fruits.splice(0, 2);// ["Apple", "Banana"] NB: l' array stesso é cambiato!
slice(idxStart,idxEnd) ritorna un nuovo array contenente gli elementi compresi tra idxStart e
idxEnd
fruits.slice(0, 2);// ["Apple", "Banana", "Orange"] NB: l' array non é cambiato!
26. DAY ONE - DATA TYPES
Arrays - Manipolazione massiva
Le tre principali funzioni per scorrere un array sono
map rimappa un array in un altra lista, i cui valori sono determianti da una funzione in ingresso a cui viene
passato ogni singolo elemento
let numbers = [1, 3, 6];
let pow = numbers.map(function(item) { return item*item;}); // pow conterrá le potenze dell' array iniziale
filter ritorna un sottoinsieme dell' array i cui elementi soddisfino le condizioni della funzione passata in input
let numbers = [1, 3, 6, 17, 22];
let filtered = numbers.filter(function(item) { return item < 10}); //filtered conterrá solo gli elementi i cui valore é piú basso di 10
reduce trasforma un array in un altro oggetto (passato in input come secondo parametro) ciclando ogni
elemento
let numbers = [1, 3, 6, 17, 22];
let total = numbers.reduce(function(total, item) { return total+item}, 0); //total = 49
la funzione in ingresso prende per primo parametro l' accumulatore (oggetto che di volta in volta viene ritornato), l'
elemento N dell' array, l'indice dell' elemento (opzionale), l' array stesso che contiene l' elemento
27. DAY ONE - DATA TYPES
Regular expressions
Una regular expression é un' automa per la ricerca di pattern all' interno di una stringa.
let re = /world/;
console.log(re.test("Hello world!!")); // returns true;
console.log(re.test("Hello word")); // returns false;
possono essere molto potenti e utilizzate per validazioni di campi o per estrarre particolari campi da
stringhe di cui conosciamo la struttura. Esempio di regular expression di validazione di un codice fiscale:
let reCf = /^(?:(?:[B-DF-HJ-NP-TV-Z]|[AEIOU])[AEIOU][AEIOUX]|[B-DF-HJ-NP-TV-Z]{2}[A-Z]){2}(?:([dLMNP-V]){1}(?:([dLMNP-V]){1}(?:[w]{1,2}|([A-
EHLMPR-T](?:[04LQ][1-9MNP-V]|[1256LMRS][dLMNP-V])|[DHPS][37PT][0L]|[ACELMRT][37PT][01LM])(?:[w]{1,3}|([A-MZ][1-9MNP-V][dLMNP-V]{2}|[A-
M][0L](?:[1-9MNP-V][dLMNP-V]|[0L][1-9MNP-V]))([A-Z]){0,1}){0,1}){0,1}){0,1}){0,1}$/i;
var isValidCf = reCf.test("RSSMRA90R11F205H"); // returns true if it is a valid CF
Il mondo delle RegExp é vasto, comprende flags, sets di caratteri, sistemi di raggruppamento e molto
altro. Per saperne di piú: https://javascript.info/regular-expressions
28. DAY ONE - DATA TYPES
Functions
Le funzioni sono blocchi di codice (routines) che eseguono particolari tasks.
Una funzione viene attivata tramite chiamata (call) da parte di "qualcuno".
Le funzioni sono oggetti, in quanto tali possono essere assegnate alle
variabili, passate come parametro, essere un valore di ritorno di una funzione
29. DAY ONE - DATA TYPES
Functions Invocation
Definita una funzione
function doSomething(a, b) {
return a*b;
}
possiamo usare strategie diverse di invocazione:
1 - doSomething(10, 3);
2 - doSomething.call(null, 10, 3)
3 - doSomething.apply(null, [10, 3])
30. DAY ONE - DATA TYPES
Functions - Call & Apply
nei casi di call e apply il primo parametro della funzione é l' oggetto di contesto.
La keyword this che si riferisce all' oggetto di contesto con cui é stata invocata la
funzione
function doSomething() {
return this.firstName + " " + this.lastName;
}
var person = {firstName: "John", lastName: "Doe"};
doSomething.call(person);
doSomething.apply(person);
//in both cases return is John Doe"
31. DAY ONE - DATA TYPES
Functions - Types
Declared
function functionName(parameters) {
//do something;
}
Anonymous (self invoking function)
(function(parameters) {
//do something;
}());// note the parenthesis at the end and wrapping the function
Function expression (a function expression is stored in a variable)
var myFunction = function(parameters) {
//do something;
}
myFunction(myParam1, myParam2, myParamX); // function call
32. DAY ONE - DATA TYPES
Functions - Arrow (ES6)
Le funzioni a freccia é una sintassi piú compatta della definizione di una funzione
Il seguente codice:
var myFunction = (aString) => aString.length;
é equivalente a:
var myFunction = function(aString) => {
return aString.length;
}
la compattazione del codice é evidente nella manipolazione degli array
let materials =["Hydrogen","Helium", "Lithium","Beryllium"];
let materialLength = materials.map(item => item.length); // [8, 6, 7, 9]
33. DAY ONE - DATA TYPES
typeof & instanceof
Sono due keyword per testare se una variabile contiene una certo tipo di dato
Usando typeof otteniamo la rappresentazione in formato stringa del tipo di oggetto
typeof 'example string' == 'string'; // true
Usando instanceof si compara il Type con cui é stato dichiarato in fase di costruzione
[] instanceof Array; // true
Usa typeof per le variabili primitive, instanceof per gli oggetti complessi
var MyClass = function () {};
var instance = new MyClass();
typeof instance; // object
instance instanceof MyClass; // true
34. DAY ONE - DATA TYPES
ES6 Features - Notable mentions
String template literals
var first ="John";
var last = "Doe";
var name = `Your name is ${first} ${last}.`;
Default parameters value
var link = function(height = 50, color = 'red', url = 'http://loremipsum.com') {
...
}
Spread operator ( ... )
function myFunction(x, y, z) { }
var args = [0, 1, 2];
myFunction(...args);
35. DAY ONE - EXERCISES
Let's try it...
What is the value of the hello variable in the following expression?
var hello;
36. DAY ONE - EXERCISES
Let's try it...
What is the value of the hello variable in the following expression?
var hello; ===> undefined
37. DAY ONE - EXERCISES
Let's try it...
What does the following expression return?
var x = 3 / "bob";
38. DAY ONE - EXERCISES
Let's try it...
What does the following expression return?
var x = 3 / "bob"; ===> NaN
39. DAY ONE - EXERCISES
Let's try it...
What is the result of "80" + 71.2:
A - 151.2
B - 151
C - "8071.2"
40. DAY ONE - EXERCISES
Let's try it...
What is the result of "80" + 71.2:
A - 151.2
B - 151
C - "8071.2"
C - "8071.2"
41. DAY ONE - EXERCISES
Let's try it...
What is the result of 2 +"2":
A - 4
B - "4"
C - "22"
42. DAY ONE - EXERCISES
Let's try it...
What is the result of 2 +"2":
A - 4
B - "4"
C - "22"
C - "22"
43. DAY TWO - STATEMENTS
Statements
Gli statements eseguono istruzioni, assegnazioni, dirigono i flussi sui diversi
blocchi di codice
Conditional statements: if/else/else if, switch
Loop statements: for, while, do..while
Error handling: try/catch/finally
44. DAY TWO - STATEMENTS
if/else if/else Statement
if é la keyword per descrivere un flusso di azioni in base a condizioni differenti
if (condition) {
block of code to be executed if the condition is true
}
else é la keyword per definire il blocco di codice da eseguire se la condizione di if é false
if (condition) {
block of code to be executed if the condition is true
} else {
block of code to be executed if the condition is false
}
else if é la keyword per definire una nuova condizione nel caso la if non sia stata soddisfatta
if (condition) {
block of code to be executed if the condition is true
} else if (condition2) {
block of code to be executed if the condition is false and condition2 is true
}
45. DAY TWO - STATEMENTS
while/do while Statement
while é la keyword per descrivere un flusso di azioni iterate finché la condizione non é
false
while (condition) {
block of code to be executed till condition become false
}
do é la keyword, unita a while (in coda), che descrive il medesimo flusso, la
differenza é che la prima iterazione viene eseguita sempre.
do {
i will be executed at least 1 time!
block of code to be executed till condition become false
} while (condition);
46. DAY TWO - STATEMENTS
for Statement
for é la keyword per descrivere un flusso di azioni iterate un numero definito di volte:
for (var i=0; i < heroes.length; i++) {
console.log(heroes[i].name); //prints all heroes names from the array
}
for...in é una sintassi per ciclare le properties su un oggetto
var hero = {name: "Batman", superpower: "Richness"};
for (x in hero) {
console.log(x+"="+hero[x]); //prints all properties and values of hero object
}
47. DAY TWO - STATEMENTS
switch Statement
switch - case é la keyword per indirizzare in un blocco di codice basandosi sul valore di una variabile
switch (hero.name) {
case "Batman":
takeBatMobile();
break;
case: "Superman":
useSuperSpeed();
break;
default: break;
}
break é la keyword con cui si esce dal blocco case (evita di eseguire altri test sullo switch e ottimizza)
default é la keyword all' interno dello switch per definire il blocco di codice da eseguire se nessuno dei
case é soddisfatto
48. DAY TWO - STATEMENTS
try/catch/finally/trow Statement
try/catch definisce un blocco di codice con eccezione controllata
try {
someRiskyFunction();
} catch(e) {
console.log(e);
}
throw é l' istruzione che permette di rilanciare un errore
throw "Error2"; // String type
throw 42; // Number type
throw true; // Boolean type
throw {toString: function() { return "I'm an object!"; } };
finally definisce un blocco di codice che verrá eseguito indipendentemente dall' esito all' interno della try/catch
try {
someRiskyFunction();
} catch(e) {
console.log(e);
} finally {
console.log("This block will be executed in any case");
}
49. DAY TWO - BUILTIN FEATURES
Scope
Lo scope di una variabile definisce il livello di appartenenza della stessa all' interno
del flusso di codice
Local scope: l' accesso alla variabile é ristretto all' interno di un blocco di codice
Global scope: l' accesso é garantito su tutti i blocchi di codice
Una variabile definita in una funzione é accessibile da una sua sottofunzione
50. DAY TWO - BUILTIN FEATURES
Scope
Globale
var i = 5; // is accessible inside functions, but everyone can access and change it
function doSomething() {
return i*2;
}
Locale
function doSomething() {
var i = 5; // i is accessible only inside this function
return i*2;
}
Nested Function
function doSomething() {
var i = 5; // i is accessible inside this function and its subfunction
function doSomethingElse() { return i*2; }
doSomethingElse();
return i;
}
51. DAY TWO - BUILTIN FEATURES
Closure
“Una closure è quello che una funzione è capace di ricordare del contesto (lexical
scope) dalla quale proviene, anche se viene eseguita al di fuori di esso.”
Permette di isolare il contesto di variabili
52. DAY TWO - BUILTIN FEATURES
Closure
Per isolare una variabile, al fine di renderla accessibile solo all' interno di un contesto e
mantenendo il suo stato, usiamo le Function Closure sfruttando le self invoking functions:
var counterFunction = (function() {
var counter = 0;
return function() {
return ++counter;
}
}());
La funzione viene invocata nel momento in cui viene definita la variabile counterFunction, in
questo modo possiamo invocare counterFunction() che ritornerá il valore incrementato di
counter
console.log(counterFunction()); // returns 1
console.log(counterFunction()); // second time, returns 2
53. DAY TWO - BUILTIN FEATURES
Prototypes
Un oggetto puó ereditare (o estendere) un altro oggetto (che fa da prototipo)
Non é consigliabile estendere i tipi di base (js versions conflicts and many more
issues!)
Old ways vs New Ways (ECMAScript 2015)
54. DAY TWO - BUILTIN FEATURES
Prototypes - the old way
Prima dell' avvento delle “classes”, per creare un oggetto:
function Cat(name) {
this.name = name;
this.meow = function () {
return this.name + " meow !";
}
}
var cat = new Cat("Garfield");
console.log(cat); // prints Cat { name:'Garfield'}
console.log(cat.meow()); //prints "Garfield meow !"
Problemi con le "new"?
var cat = Cat("Garfield"); // error! this is undefined
console.log(cat);
55. DAY TWO - BUILTIN FEATURES
Prototypes - the old way
Estendere un oggetto con prototype
function Animal(name) {
this.name = name;
}
Animal.prototype.constructor = Animal;
Animal.prototype.speak = function () {
return "My name is " + this.name;
};
function Cat(name) {
Animal.call(this, name); //call super constructor Animal
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
cat = new Cat("Garfield");
console.log(cat.speak());// prints "My name is Garfield"
56. DAY TWO - BUILTIN FEATURES
Prototypes - the old way
La proprietá __proto__ é un accessor di Object.prototype che permette di definire
anch'esso il prototipo di un oggetto che si vuol creare. É una feature deprecata e
comporta varie issue di performance
Estendere un oggetto con __proto__
var Animal = function() {
}
var cat = {};
var animal = new Animal();
car.prototype.__proto__ = animal; //DO NOT USE
Un modo migliore é l' utilizzo di Object.create
var cat = Object.create(animal); //extends properties and methods of animal, without affecting the "animal" variable
57. DAY TWO - BUILTIN FEATURES
Prototypes - the new way
Introdotto il concetto di “classi”
Codice piú pulito e senza fraintendimenti sulla variabile this
Piú object oriented
58. DAY TWO - BUILTIN FEATURES
Prototypes - the new way
Estendere un oggetto
class Animal {
constructor(name) {
this.name = name;
}
speak() {
return "My name is " + this.name;
}
}
class Cat extends Animal {
constructor(name) {
super(name);
}
}
let cat = new Cat("Garfield");
cat.speak();
59. DAY TWO - BUILTIN FEATURES
Timeouts - postponing execution
Il timeout é una funzionalitá (praticamente una function) built-in sul browser.
Permette di ritardare l'esecuzione della function passata come parametro
É possibile cancellare l' esecuzione (se si ha necessitá di farlo)
Esempio:
let myFunction = function () {
console.log("Hello!");
};
var timeoutId = setTimeout(myFunction, 1000); //prints "Hello!" after 100 milliseconds
//clearTimeout(intervalId); // uncomment this if you want to stop the timeout execution
60. DAY TWO - BUILTIN FEATURES
Interval - repeating Timeouts
L' interval permette di eseguire funzioni a intervalli regolari di tempo, é di fatto un timeout ripetuto
É possibile cancellare la schedulazione dell' intervallo (se si ha necessitá)
Esempio:
let myFunction = function () {
console.log("Hello!");
};
var intervalId = setInterval(myFunction, 100); //prints "Hello!" at intervals of 100 milliseconds, forever and ever...
//clearInterval(intervalId); //uncomment if you want to stop the interval, otherwise it will keep going
61. DAY TWO - BUILTIN FEATURES
Callbacks
Una callback (o higher-order function) é un design pattern che prevede
una funzione passata come parametro (argument) ad un' altra funzione ed
eseguita in un determinato momento da quest' ultima;
Sono soprattutto utili in caso di funzioni asincrone (il risultato non é disponibile
al momento dell' uscita dalla funzione invocata), come Timeouts, Intervals o le
Promises che verranno trattate piú avanti
62. DAY TWO - BUILTIN FEATURES
Callbacks
Esempio di callback
function doSomethingAndNotify(a, b, fnCB) {
var computed = a + b;
var options = {computedValue: computed};
setTimeout(function () {
fnCB(options);
}, 100);
}
doSomethingAndNotify(1, 2, function (options) { //this is my callback fnCB!!!
console.log(options.computedValue); // prints the resulting computation, well done!
});
63. DAY TWO - BUILTIN FEATURES
Promises
Una Promise é un oggetto che rappresenta l' eventuale completamento di un task asincrono
Native da ECMAScript 6
Ha un costruttore con una funzione che prende due parametri in ingresso:
resolve completamento riuscito
reject completamento fallito
L'esito del task asincrono é gestibile attraverso due metodi:
then prende in input una funzione di callback per il completamento riuscito
catch prende in input una funzione di callback per il completamento fallito
La funzione di callback di completamento riuscito puó ritornare un' altra promise o un
oggetto, permettendo il chaining di piú Promises
64. DAY TWO - BUILTIN FEATURES
Promises Native
Esempio di una Promise nativa
let heroes = [{name: "Batman"}, {name: "Robin"}];
let findHeroesNames = function () {
return new Promise((resolve, reject) => {
if (heroes) resolve(heroes.map(item => item.name)); else reject(heroes);
});
};
findHeroesNames().then(function (heroes) {
console.log(heroes); //prints an array ["Batman", "Robin"]
}).catch(function (err) {
console.log("Something went wrong here: " + err);
});
65. DAY TWO - BUILTIN FEATURES
Promises - Chaining
Il Chaining permette di avere delle operazioni asincrone a catena, eseguite una dopo l' altra
Esempio di una Promise chain
let heroes = [{name: "Batman", superpower:"Cleverness"}, {name: "Robin", superpower: "Friend of Batman"} ];
let findHeroes = function() {
return new Promise(resolve, reject) {
if (heroes) resolve(heroes);
else reject(heroes);
}
}
findHeroesNames().then(function(heroes) {
console.log("I've got "+ heroes.length+" heroes"); //prints the array of heroes object
return heroes.map(item => item.supepower); // could return another async operation
}).then(function(heroesPowers) {
console.log(heroesPowers); //prints ["Cleverness", "Friend of Batman"]
}).catch(function (err) {
console.log("Something went wrong here: "+err);
});
66. DAY TWO - BUILTIN FEATURES
Promises - Branching
Il branching aggancia la stessa promise a multipli callback (invocati parallelamente)
Esempio di una Promise Branch
let heroes = [{name: "Batman", superpower:"Cleverness"}, {name: "Robin", superpower: "Friend of Batman"} ];
let findHeroes = function() {
return new Promise(resolve, reject) {
if (heroes) resolve(heroes);
else reject(heroes);
}
}
let findPromise = findHeroesNames();
findPromise.then(function(heroes) {
console.log("I've got "+ heroes.length+" heroes");
return heroes.map(item => item.supepower);
});
findPromise.then(function(heroes) { // still receiving heroes instead of heroes name!!!
console.log(heroes);
});
66
67. DAY TWO - ECMASCRIPT6 MODULES
Importing and Exporting
Nella vecchia concezione di client javascript per utilizzare variabili attraverso vari files
occorreva definire variabili globali, causando la proliferazione di oggetti sparsi su tutta l'
applicazione di cui quasi non era possibile determinare l' origine e avendo come vincolo l'
ordine specifico dei file da importare su browser
La community JS ha generato negli anni varie soluzioni per ovviare al problema creando degli
standard che definiscono i meccanismi di modularizzazione. I piú importanti sono
1. Asynchronous Module Definition (AMD) : implementato da RequireJS
2. CommonJS Modules: implementato in Node.js
I moduli introdotti in ES6 sono un' evoluzione dei 2 principali contendenti, racchiudono le
migliori caratteristiche e ne riducono i difetti.
67
68. DAY TWO - ECMASCRIPT6 MODULES
Importing and Exporting
The Exports keyword
// lib.js
export const sqrt = Math.sqrt;
export function square(x) {
return x * x;
}
export function diag(x, y) {
return sqrt(square(x) + square(y));
}
Possiamo ora importare le funzioni in un altro file senza infarcire di variabili l'
applicazione
68
69. DAY TWO - ECMASCRIPT6 MODULES
Importing and Exporting
The Import keyword
// main.js
import { square, diag } from 'libs'; // picking some exports from lib
import * as lib2 from 'lib2'; // importing all exports from lib2, with alias
console.log(square(11)); // square is available from lib
console.log(diag(4, 3)); // also diag is available
console.log(lib2.whateverMethod());// using whateverMethod from lib2
Questo sistema rende piú pulito, ordinato e gestibile il progetto
Possiamo esportare in modo totalmente flessibile classi, variabili e funzioni
69
70. DAY TWO - EXERCISE
Let's try it...
Scrivere una funzione che converta un numero intero in un array che per ogni
elemento contiene una cifra del numero. es:
digitize(123) output --> [1,2,3]
digitize(1230) output --> [1,2,3,0]
71. DAY TWO - EXERCISE
Let's try it...
Scrivere una funzione che converta un numero intero e restituisca un array che per
ogni elemento contiene una cifra di tale numero. es:
digitize(123) output --> [1,2,3]
digitize(1230) output --> [1,2,3,0]
Soluzione
const digitize = n => [...`${n}`].map(i => parseInt(i));
72. DAY THREE - TYPESCRIPT
Typescript
Angular é scritto in questo linguaggio, é un superset di javascript che permette strutture tipizzate
nello stile OO (classi e interfacce). Il maggior beneficio é la facilitazione nel supporto degli ambienti
di lavoro, error spotting e type checking che finora con javascript risultavano parziali e imprecisi.
Esempio di sintassi per un' interfaccia (in questo caso un' entitá)
interface GreetingSettings {
greeting: string;
duration?: number; //nullable properties have question mark
color?: string;
}
let MyGreet: GreetingSettings = {greeting: "Hello", duration: 10, color:blue};
73. DAY THREE - TYPESCRIPT
Typescript
Sintassi di dichiarazione di variabili
[accessor] [identifier] : [type-annotation] = [value];
sia l' annotazione del tipo che il valore sono opzionali, omettendo la type
annotation il tipo sará any (non consigliato), omettendo il valore la variabile é
inizializzata a undefined.
private x: Widget = getWidget(1);
Sintassi di dichiarazione di una funzione
[accessor] [identifier]( [argumentName]: [argumentType] ): [type-annotation];
74. DAY THREE - TYPESCRIPT
Typescript - Interfaces and classes
interface Drivable {
start(): void;
drive(distance: number): boolean;
}
class Car implements Drivable {
private _isRunning: boolean;
constructor() {
this._isRunning = false;
}
public start() {
this._isRunning = true;
}
public drive(distance: number): boolean {
if (this._isRunning) {
return true;
}
return false;
75. DAY THREE - TYPESCRIPT
Typescript - Interfaces and classes
Un parametro dichiarato nel costruttore diventa una proprietá della classe
export class Hero {
constructor(
public id: number,
public name: string,
public power: string,
public alterEgo?: string
) { }
stringify(): string {
return this.id + "-"+this.name; //properties into this object
76. DAY THREE - TYPESCRIPT
Typescript - Using a type variable
Data una semplice classe
class Hero {
id: number;
name: string;
}
dichiariamo e inizializziamo la variabile
hero: Hero = { id: 1, name: "Batman"};
oppure:
hero: Hero = new Hero();
77. DAY THREE - TYPESCRIPT
Typescript - Features
Overloading functions
public getWidget(n: number): Widget;
public getWidget(n: string): Widget;
Type Alias
type GreetingLike = string | (() => string) | MyGreeter;
private greet(g: GreetingLike): void;
78. DAY THREE - TYPESCRIPT
Typescript - Features
Namespaces Per organizzare le classi in diversi contesti
namespace GreetingLib.Options {
// Refer to via GreetingLib.Options.Log
interface Log {
verbose?: boolean;
}
interface Alert {
}
}
79. DAY THREE - ANGULAR
Angular - A beginner guide
79
80. DAY THREE - ANGULAR
Angular - A beginner guide
Angularjs (1.x), Angular 2, 4, 5 or 6??
80
81. DAY THREE - ANGULAR OVERVIEW
Angular - Overview
Angular é un framework per sviluppare applicazioni client (browser) single page che
riunisce i migliori design pattern della storia di javascript in un' unica soluzione
Modules: i moduli di angular (NgModules) definiscono un contesto di compilazione di un
set di componenti dedicati a un particolare dominio applicativo.
Components: i componenti controllano una parte dello schermo e separano la logica di
presentazione dall' aspetto grafico dell' app, assumendo il compito di
Controller/ViewModel nel modello MVVM
Services: i servizi sono una categoria di oggetti iniettabili sui componenti e progettati per
eseguire specifici task. Permettono ai componenti di occuparsi della sola logica di
visualizzazione rendendoli piú efficienti e semplificati
81
82. DAY THREE - ANGULAR OVERVIEW
Angular - Overview
Directives: come i componenti, si occupano di cambiare l' aspetto della parte DOM
di cui sono responsabili
Templates: utilizzati dai components, i template rappresentano l' aspetto grafico dell'
applicazione, ossia la View sul modello MVVM
Injector: é un elemento fondamentale di Angular, che si preoccupa di fornire i servizi
ai componenti in modo dichiarativo
82
83. DAY THREE - ANGULAR OVERVIEW
Angular - Brief FUNDAMENTALS of MVVM
É un pattern architetturale che si propone la separation of concerns, ossia che ogni
categoria di elementi costituenti un software svolgano determinati e precisi compiti. Si
compone di:
Model: é il modello di dominio (o una sua derivazione), ció che rappresenta la struttura
di dati che si vuole visualizzare e gestire.
View: la vista rappresenta il layout e la user experience dell' app. Non dovrebbe
contenere logica se non strettamente collegata all' aspetto grafico di cosa vede l'utente
View-Model: é l' intermediario tra il modello di business e il modello.
“Il view-model fornisce quindi i dati dal modello in una forma che la vista può usare
facilmente.”
84. DAY THREE - ANGULAR OVERVIEW
Angular - Ecosystem
Angular Cli (former DevKit) sistema comprensivo per lo sviluppo, gestione e
deploy dei progetti
Node.js[v8+] and npm server js e package manager per installare librerie di
progetto
TypeScript un linguaggio tipizzato che compila in javascript
Jasmine/Protractor framework per test unitari e e2e
.....continua
85. DAY THREE - ANGULAR OVERVIEW
Angular - Ecosystem
TypeScript il nuovo linguaggio tipizzato che compila in js
Webpack 4 il tool per la build e packaging
Angular Cli (former DevKit) sistema comprensivo per lo sviluppo, gestione e
deploy dei progetti
Node.js[v8+] and npm server js e package manager per installare librerie di
progetto
Jasmine/Protractor framework per test unitari e e2e
86. DAY THREE - ANGULAR ARCHITECTURE
Architettura del flusso dei componenti
87. DAY THREE - ANGULAR ARCHITECTURE
Anatomia di un NgModule
88. DAY THREE - ANGULAR ARCHITECTURE
NgModule
Un modulo Angular racchiude, dichiara e rende disponibili componenti e servizi.
Dichiarazione dei metadati (decoration):
imports [] dichiarazione di tutti i moduli che si vogliono utilizzare
exports [] componenti e servizi visibili all' esterno del modulo
declarations [] componenti che il modulo utilizza
bootstrap [] il componente root che angular inizializza nel file index.html
89. DAY THREE - ANGULAR ARCHITECTURE
Data binding
Business Logic
(TypeScript)
Template View
(usually HTML)
SYNCHRONIZATION
90. DAY THREE - ANGULAR ARCHITECTURE
Data binding
Interpolation Binding (One-way component-to-view)
<p>4 + 4 = {{4+4}}</p>
<p>My favourite hero is {{hero.name}}</p>
Property Binding/Attribute/Css Class (One-way component-to-view)
<img [src]="product.imageUrl" [title]='product.productName'/>
<th [attr.colspan]="2" class="txtcenter"></th>
<td [class.txtright]="{{booleanExpression}}">Hero Details</th>
91. DAY THREE - ANGULAR ARCHITECTURE
Data binding
Event Binding (One-way view-to-component)
<button (click)="updateProduct()">
Update
</button>
Two-Way Binding
<input type="text" [(ngModel)]="firstName">
92. DAY THREE - ANGULAR ARCHITECTURE
Pipes (operatore | )
I Pipes sono disegnati allo scopo di trasformare i valori degli oggetti (piú complessi di
Number, String) in un formato rivolto alla visualizzazione dei dati su schermo.
Esempio di una pipe built in per trasformare le Date sulla view di un componente:
<p>Your birthday is {{ birthday | date }}</p> //formato di default
<p>Your birthday is {{ birthday | date:"MM/dd/yy" }} </p>//formato specifico
94. DAY THREE - ANGULAR ARCHITECTURE
Pipes(operatore | ) - Custom
@Pipe (decorator):definisce un nuovo Pipe agganciata a una classe
PipeTransform (interface): la classe del pipe implementa questa classe che espone un metodo
transform(value, param1,param2..paramN) di cui il primo parametro é il valore che si deve convertire, gli altri
eventuali parametri in input
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'exponential'})
export class ExponentialPipe implements PipeTransform {
transform(value: number, exponent: string): number {
let exp = parseFloat(exponent);
return Math.pow(value, isNaN(exp) ? 1 : exp);
}
}
Uso nella view
<p>
Super Hero Power: {{power | exponential: factor}}
</p>
95. DAY THREE - ANGULAR ARCHITECTURE
Pipes (operatore | ) - Pure e inpure
Pipe Pure:eseguite ogni volta che un cambio nel valore (primitivo o ref. dell' oggetto)
viene rilevato
Pipe Inpure: eseguite ogni volta che un cambio nel componente viene rilevato
@Pipe({
name: 'myTransformImpure',
pure: false
})
96. DAY THREE - ANGULAR ARCHITECTURE
Pipes (operatore | ) - Filtrare e ordinare liste
In angularjs (1.x) esistevano le pipe filter e orderBy, sono state omesse per problemi
di performance e minificazione
Si raccomanda di spostare la logica di filtering/ordering dentro il componente
97. DAY THREE - ANGULAR ARCHITECTURE
Angular CLI
E' uno strumento a riga di comando eseguibile che va installato tramite npm (-g
flag per utilizzo a livello globale)
Permette di generare struttura del progetto, ng-modules (non js modules),
componenti, servizi e altro, eseguire la build per la generazione del pacchetto di
distribuzione, eseguire i test e lanciare l' app.
98. DAY THREE - ANGULAR ARCHITECTURE
Angular CLI - Principali features
Comando Descrizione
ng new Creazione di progetto
ng generate Generazione modules, components, routes, services & pipes
ng serve Lancio dell'applicazione
ng build Build e creazione distribuzione
ng test Avvio test unitari
ng e2e Avvio test e2e
ng lint Usa un linter (controllo di errori) sul codice
99. DAY THREE - TUTORIAL
Tutorial
TOUR OF HEROES -
PART 1
ANGULAR CLI
100. DAY THREE - ANGULAR ARCHITECTURE
Change detection
La Change Detection é una caratteristica fondamentale di Angular, consiste nel
rilevare i cambiamenti nel modello e nella vista, sincronizzarli autonomamente e
notificare i listener registrati
Cosa causa i cambiamenti?
- Eventi (click del pulsante, submit di form, selezione di una option da combo)
- Chiamate Remote (fetch di dati su server)
- Timers (timeouts & intervals)
in generale, qualsiasi operazione asincrona
101. DAY THREE - ANGULAR ARCHITECTURE
Components
I Component sono i building block che controllano porzioni di schermo
Si implementano su due entitá distinte (component-class e component-view)
Una component-view puó contenere altri child components
Nella definizione della component-class si specifica il tag html che permette ad
angular di includere il component
102. DAY THREE - ANGULAR ARCHITECTURE
Component declaration & Change detection in action
Component class (hero.component.ts)
@Component({
selector: 'app-heroes',
templateUrl: './heroes.component.html',
styleUrls: ['./heroes.component.css']
})
export class HeroesComponent implements OnInit {
text = 'Some text to change';
constructor() {}
changeText() {
this.text = 'Another longer longer text to change';
}
}
View template (hero.component.html)
<div>
<label>My text is {{text}}</label>
<button (click)="changeText()">Change</button>
</div>
103. DAY THREE - ANGULAR ARCHITECTURE
Component in depth - @Input
Struttura parent-child component
parent-view
<app-child [childMessage]="'myMessage'"></app-child>
child-component
export class ChildComponent {
@Input() childMessage: string;
constructor() {
}
}
104. DAY THREE - ANGULAR ARCHITECTURE
Component in depth - @Output
parent-view
<app-child (messageEvent)="receiveMessage($event)"></app-child>
parent-component
export class ParentComponent {
constructor() { }
receiveMessage($event) {
this.message = $event
}
}
child-component
export class ChildComponent {
@Output() messageEvent = new EventEmitter<string>();
message = "Hello"
constructor() {
}
sendMessage() {
this.messageEvent.emit(this.message)
}
}
105. DAY THREE - ANGULAR ARCHITECTURE
Component in depth - LifeCycle Hooks
Angular gestisce tutto il ciclo di vita di un componente (create, init, change detection,
destroy).
Ogni componente puó definire delle funzioni richiamate da angular durante le varie fasi.
Le piú importanti sono
ngOnChanges(SimpleChanges) - richiamata ogni qualvolta uno o piú @input cambiano di valore
ngOnInit() - richiamata una sola volta dopo ngOnChanges
ngDoCheck() - richiamata ad ogni change detection (N.B. molto pericolosa se non la si usa bene)
ngOnDestroy() - richiamata prima che angular distrugga il component (utile per rilasciare risorse ed
evitare memory leaks)
106. DAY FOUR - ANGULAR FUNDAMENTALS
Forms and Validation
Angular gestisce gli elementi dei form (input, select, checkbox...) usando il
databinding two-way per sincronizzare il model con la view
<input [(ngModel)]="hero.name" placeholder="name"/>
Se occorre essere notificati, ad esempio ad ogni carattere digitato sulla input, si
aggancia un event-binding con una funzione
<input (keyup)="onKey($event)"> //onKey is a function of the component
N.B: Gli event binding possono passare degli oggetti particolari, gli $event, che
contengono anche l' elemento HTML che scatena l' evento, in questo caso un InputEvent
107. DAY FOUR - ANGULAR FUNDAMENTALS
Forms and Validation
É possibile sfruttare le direttive per il binding di dati
<select [(ngModel)]="hero.power" name="power">
<option *ngFor="let pow of hero.powers" [value]="pow">{{pow}}</option>
</select>
verrá renderizzata una option per ogni power (array) dell' hero
108. DAY FOUR - ANGULAR FUNDAMENTALS
Forms and Validation
import {FormsModule} from '@angular/forms';
Per attivare le funzionalitá built-in dei Forms, dichiarare nel modulo (solitamente nel root
module)
@NgModule({
imports: [
FormsModule,
...
]
})
109. DAY FOUR - ANGULAR FUNDAMENTALS
Forms and Validation
Classi css applicate all' elemento in base al suo stato nel form
110. DAY FOUR - ANGULAR FUNDAMENTALS
Forms and Validation
Dichiarazione di una variabile (nella view)
<input name="name" required [(ngModel)]="hero.name" #name="ngModel" >
Utilizzo dei validator (required é anche una direttiva ng!!!)
<div class="error" *ngIf="name.invalid && (name.dirty || name.touched) &&
name.errors.required">
Name is required.
</div>
N.B.: errors contiene un oggetto con tutti i tipi di errore rilevati per quell' elemento
111. DAY FOUR - ANGULAR FUNDAMENTALS
Forms and Validation - Reactive
import {ReactiveFormsModule} from '@angular/forms';
Per attivare le funzionalitá built-in dei Forms, dichiarare nel modulo (solitamente nel root
module)
@NgModule({
imports: [
ReactiveFormsModule,
...
]
})
112. DAY FOUR - ANGULAR FUNDAMENTALS
Forms and Validation - Reactive
Reactive Forms é una variante alla gestione dei Forms classica.
In questa formula la variabile del form denominata "name" é dichiarata nel component
name = new FormControl(this.hero.name);
sulla view
<input type="text" [formControl]="name">
Come form:
heroForm = new FormGroup({
'name': new FormControl(this.hero.name, [Validators.required])
})
113. DAY FOUR - ANGULAR FUNDAMENTALS
Forms and Validation - Reactive
I Custom Validators sono funzioni che accettano un AbstractControl in input
myValidator: {[key: string]: any} = (control: AbstractControl) => {
let wrongValue = wrongRegExp.test(control.value);
return wrongValue ? {'wrongMessageKey': {value: control.value}} : null;
}
(aderiscono all' interfaccia ValidatorFn)
dopodiché aggiungerlo
heroForm = new FormGroup({
'name': new FormControl(this.hero.name, [Validators.required])
})
N.B. Si possono creare anche attribute direttive nel caso si opti per un approccio "view" (vedere
tutorial angular)
114. DAY FOUR - ANGULAR FUNDAMENTALS
Forms and Validation - Dynamic
Dynamic forms é una strategia di creazione (dinamica) dei Form.
i singoli campi (form controls) si descrivono tramite oggetti.
export class DropdownControl extends BaseControl { //definire BaseControl come superclasse di tutti i controlli
controlType = 'dropdown';
options: {key: string, value: string}[] = [];
}
nella view (ciclando i form controls)
<div [ngSwitch]="control.controlType">
<select [id]="control.key" *ngSwitchCase="'dropdown'" [formControlName]="control.key">
<option *ngFor="let opt of control.options" [value]="opt.key">{{opt.value}}</option>
</select>
...other switch case
</div>
115. DAY FOUR - TUTORIAL
Tutorial
TOUR OF HEROES -
PART 2
COMPONENTS
116. DAY FOUR - ANGULAR ARCHITECTURE
Directives
Component
<app-messages></app-messages>
Structural directive (manipolano gli elementi html, es: aggiungono o
rimuovono nodi dal DOM)
<li *ngFor="let hero of heroes">
Attribute directive
<li [ngStyle]="{'font-size.px':24}"></li>
117. DAY FOUR - ANGULAR ARCHITECTURE
Attribute Directives
Non hanno bisogno di dichiarare template
Cambiano l' aspetto dell' elemento a cui sono agganciate
@Directive decorator (https://angular.io/api/core/Directive)
@Directive({
selector: '[appHighlight]'
})
export class HighlightDirective {
constructor(el: ElementRef) {
el.nativeElement.style.backgroundColor = 'yellow';
}
}
Uso nella view
118. DAY FOUR - ANGULAR ARCHITECTURE
Structural Directives - Main Built-in features
ngFor : interpreta una espressione di angular ciclando gli elementi di un array in input.
<li *ngFor="let hero of heroes">{{hero.name}}</li>
il risultato sará una transclude di tanti elementi <li> quanti sono i valori nell' array heroes e
contenenti ognuna il nome dell' hero relativo.
altre Features:
index: variabile predefinita che rappresenta l'indice dell'array che si sta ciclando
tracker: ngFor non permette oggetti duplicati, il tracker serve a definire eventualmente una
variabile (ad es. id dell'oggetto o index) che faccia da identificativo della riga renderizzata
<div *ngFor="let hero of heroes; let i=index; let odd=odd; trackBy:trackById">
({{i}}) {{hero.name}}
</div>
119. DAY FOUR - ANGULAR ARCHITECTURE
Structural Directives - Main Built-in features
ngIf : interpreta una espressione di angular all'interno del valore dell' attributo con cui é
dichiarato (conditional statement if)
<div *ngIf="hero.superpower === 'X-Ray Vision'">
<p class="">{{hero.name}} can see through solid objects </p>
</div>
ngSwitch: unito a ngSwitchCase determina quale dei blocchi che soddisfano la condizione
della expression debba essere renderizzata (conditional statement switch)
<div [ngSwitch]="person.gender">
<div *ngSwitchCase="'male'">Male</div>
<div *ngSwitchCase="'female'">Female</div>
<div *ngSwitchDefault>Unknown</app-unknown-hero>
120. DAY FOUR - TUTORIAL
Tutorial
TOUR OF HEROES -
PART 3
DISPLAY DATA
121. DAY FOUR - ANGULAR ARCHITECTURE
Services
I services svolgono compiti specifici con uno scopo molto ristretto (single
responsability), ad esempio occuparsi delle notifiche all' utente, loggare
messaggi, effettuare chiamate al server per un determinato ambito
Il metadata @Injectable({ providedIn: 'root' }) permette di evitare la definizione del
servizio su ogni modulo che necessita di usarlo
@Injectable({ providedIn: 'root' })
export class Logger {
log(msg: any) { console.log(msg); }
error(msg: any) { console.error(msg); }
warn(msg: any) { console.warn(msg); }
}
122. DAY FOUR - ANGULAR FUNDAMENTALS
Dependency injection - Providers
Un DI Provider configura un' istanza di servizio iniettabile nei componenti fornendo un contesto di propagazione
(component tree). É dichiarato:
In un metadato sulla definizione di modulo
providers : [Logger]
oppure
providers : [{ provide: Logger, useClass: BetterLogger }]
nel primo caso dichiaro l' implementazione diretta della classe, nel secondo una diversa classe che estende la
classe Logger
In un metadato (aka decoration) sulla definizione di un servizio
@Injectable({
// we declare that this service should be created
// by any injector that includes HeroModule.
providedIn: HeroModule
})
123. DAY FOUR - ANGULAR FUNDAMENTALS
Dependency injection - Hierarchy
Il Root Injector fornisce la
stessa istanza di servizio
(singleton) a tutti i
componenti.
NB: Nella stragrande
maggioranza dei casi é
sufficiente configurare i servizi
in singleton sul root Injector
124. DAY FOUR - ANGULAR FUNDAMENTALS
Dependency injection - Contesto Globale o Locale?
Il decoratore @Injectable nel seguente caso configura il servizio per essere usato solo nel modulo (e i
relativi componenti) HeroModule,
import { Injectable } from '@angular/core';
import { HeroModule } from './hero.module';
import { HEROES } from './mock-heroes';
@Injectable({
// we declare that this service should be created
// by any injector that includes HeroModule.
providedIn: HeroModule,
})
export class HeroService {
getHeroes() { return HEROES; }
125. DAY FOUR - ANGULAR FUNDAMENTALS
Observables
powered by RxJs
Gli Observables rendono piú facile la gestione di operazioni asincrone (come ad
esempio le fetch di dati da server) attraverso un sistema di Publisher/Subscriber
Pattern Observer: un oggetto subject contiene una lista di oggetti observers e li
notifica automaticamente ad ogni cambio di stato
Sono l'evoluzione delle Promises (in Angular si usano al posto di queste ultime,
importando la relativa libreria)
126. DAY FOUR - ANGULAR FUNDAMENTALS
Observables
Un Observer si sottoscrive (subscribe) a un Observable per essere notificato di uno
state change
Subcribe: la subscribe accetta un oggetto Observer che contiene con tre metodi or
da 1 a 3 funzioni in input
1. next(output) funzione richiamata dal subscriber ogni volta che uno stato é
variato
2. error: funzione richiamata dal subscriber in caso di errore
3. complete: funzione richiamata dal subscriber quando si chiuderanno le
next (eventualmente per richiamare unsubscribe())
127. DAY FOUR - ANGULAR FUNDAMENTALS
Observables
Esempio di utilizzo su un service (hero.service.ts) che esegue il fetch di dati su server
getHeroes (): Observable<Hero[]> {
return this.http.get<Hero[]>(this.heroesUrl);
}
Esempio di utilizzo lato componente (hero.component.ts):
ngOnInit() {
this.heroService.getHeroes().subscribe(heroes => this.heroes = heroes);
}
128. DAY FOUR - TUTORIAL
Tutorial
TOUR OF HEROES -
PART 4 SERVICES
129. DAY FIVE - ANGULAR FUNDAMENTALS
Routing, Navigation and Parameters
Il Router integrato di Angular permette di navigare l' applicazione da una vista all' altra
130. DAY FIVE - ANGULAR FUNDAMENTALS
Routing, Navigation and Parameters
The Routes Object
export declare type Routes = Route[];
The Route Object
{path: 'dashboard', component: DashboardComponent}
131. DAY FIVE - ANGULAR FUNDAMENTALS
Routing, Navigation and Parameters
import {RouterModule, Routes} from '@angular/router';
Dichiarare nel modulo (root module o module separato)
const routes: Routes = [
{path: '', redirectTo: '/dashboard', pathMatch: 'full'},
{path: 'dashboard', component: DashboardComponent},
{path: 'list', component: ListComponent},
{path: 'detail/:id', component: DetailComponent},
];
@NgModule({
imports: [
RouterModule.forRoot(routes),
...
]
})
132. DAY FIVE - ANGULAR FUNDAMENTALS
Routing, Navigation and Parameters
The Router Outlet Component
//dichiarato su app.component.html (in una configurazione di base)
<router-outlet></router-outlet>
Inserendo questo componente nella view del componente
root, quando il browser naviga su una determinata pagina, verrá
attivato il relativo componente
133. DAY FIVE - ANGULAR FUNDAMENTALS
Routing, Navigation and Parameters - Links
Abbiamo analizzato la configurazione, ma come si definiscono i link per attivare un
componente successivo?
<a routerLink="/list" >Vai alla lista</a>
La direttiva routerLink assume il controllo della url, trasforma il path all' interno dell'
attributo
Perché non usare l' attributo href sull' anchor invece? Perché questa direttiva é
dedicata ad angular e agisce nel suo contesto, trasformando i parametri ad esempio
134. DAY FIVE - ANGULAR FUNDAMENTALS
Routing, Navigation and Parameters - Links
La direttiva routerLinkActive, in congiunzione a routerLink permette di definire classi
css nel caso in cui la url del browser corrisponda a quella definita sull' anchor
<a routerLink="/list" routerLinkActive="classForAcrive">Vai alla lista</a>
135. DAY FIVE - ANGULAR FUNDAMENTALS
Routing, Navigation and Parameters - Passaggio
Parametri
{path: 'detail/:id', component: DetailComponent}
É sufficiente impostare nella view il link come espressione one-way binding
<li *ngFor="let hero of heroes">
<a routerLink="/detail/{{hero.id}}">
</li>
Il componente attivato puó reperire i parametri attraverso l' oggetto
ActivatedRoute iniettabile nel costruttore
136. DAY FIVE - ANGULAR FUNDAMENTALS
Routing, Navigation and Parameters - Passaggio Parametri
Oggetto Activated Route: contiene info sulla route attualmente attiva, come la url, la configurazione e
i parametri (path params & queryString) passati in input
definizione in un componente:
export class DetailComponent implements OnInit {
detailObject: DetailObject;
constructor(
private route: ActivatedRoute,
private detailService: DetailService) {}
ngOnInit(): void {
const id = +this.route.snapshot.paramMap.get('id');
this.detailService.getDetail(id)
.subscribe(detail => this.detailObject = detail);
}
}
137. DAY FIVE - ANGULAR FUNDAMENTALS
Routing, Navigation and Parameters - Nested Routes
138. DAY FIVE - ANGULAR FUNDAMENTALS
Routing, Navigation and Parameters - Nested Routes
Quando definiamo una Route, aggiungiamo una proprietá children
{ path: 'list', component: ListComponent,
children: [
{ path: 'detail/:id', component: DetailComponent }
]
}
É ora sufficiente aggiungere un <router-outlet> all' interno della view di ListComponent per
cambiare il path su browser e visualizzare la sotto-view
<li *ngFor="let hero of heroes">
<a routerLink="/detail/{{hero.id}}">
</li>
<router-outlet></router-outlet>
139. DAY FIVE - TUTORIAL
Tutorial
TOUR OF HEROES -
PART 5
ROUTING
140. DAY FIVE - ANGULAR FUNDAMENTALS
Client HTTP
import {HttpClientModule} from '@angular/common/http';
Dichiarazione per l' utilizzo del modulo (nella root solitamente)
@NgModule({
imports: [
HttpClientModule,
...
]
})
141. DAY FIVE - ANGULAR FUNDAMENTALS
Client HTTP
Oggetto HttpClient: permette di invocare una url remota con il supporto REST, i metodi:
request(...params) all' interno dei parametri (posizionali o a oggetto) é possibile
configurare req. method (get, post, put delete), url e varie altre opzioni
get(...params) come la request, ma il req. method preimpostato (GET)
post(...params) come la request, ma il req. method preimpostato (POST)
put(...vari params) come la request, ma il req. method é preimpostato(PUT)
delete(...vari params) come la request, ma il req. method é preimpostato(DELETE)
Tutti i metodi ritornano un Observable, di seguito trattato
142. DAY FIVE - ANGULAR FUNDAMENTALS
Client HTTP
Injection in un service
export class HeroService {
// si puó omettere la dichiarazione della variabile nel service, http
// diventa proprietá di HeroService e utilizzabile nei suoi metodi
constructor(
private http: HttpClient) {}
143. DAY FIVE - TUTORIAL
Tutorial
TOUR OF HEROES -
PART 6
HTTP
144. DAY FIVE - ANGULAR FUNDAMENTALS
Unit Testing
Predisposizione del Test durante la generazione del componente/servizio con
angular-cli
Jasmine Framework : lo strumento che mette a disposizione infrastruttura e utility
per facilitare la scrittura di test
<myComponent>.spec.ts : i file spec contengono i testcase di un componente
ng test: shell command per eseguire i test
test.ts: contiene la conf e le opzioni per il run dei test con jasmine, di default carica
i file *.spec.ts
145. DAY FIVE - ANGULAR FUNDAMENTALS
Unit Testing - Testare una unitá
Set-up dell' environment di esecuzione (beforeEach)
Creazione di una istanza del component/service da testare
Creazione del prerequisito per testare il component/service
Invocazione del metodo soggetto del test
Controllo degli expected behaviours conseguenti all' invocazione
146. DAY FIVE - ANGULAR FUNDAMENTALS
Unit Testing - Esempi
Esempio di test basico su componente
//component
export class LightswitchComponent {
isOn = false;
clicked() { this.isOn = !this.isOn; }
}
//component.spec.ts
describe('LightswitchComponent', () => {
it('should toggle #isOn when #clicked()', () => {
const comp = new LightswitchComponent();
expect(comp.isOn).toBe(false, 'off at first');
comp.clicked();
147. DAY FIVE - ANGULAR FUNDAMENTALS
Esempio di test basico su componente
//component
export class LightswitchComponent {
isOn = false;
clicked() {
this.isOn = !this.isOn;
}
}
Unit Testing - Esempi
148. DAY FIVE - ANGULAR FUNDAMENTALS
//component.spec.ts
describe('LightswitchComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [LightswitchComponent]
}).compileComponents();
}));
it('should toggle #isOn when #clicked()', () => {
const fixture = TestBed.createComponent(LightswitchComponent);
const app = fixture.debugElement.componentInstance;
expect(comp.isOn).toBe(false, 'off at first');
comp.clicked();
Unit Testing - Esempi
149. DAY FIVE - ANGULAR FUNDAMENTALS
E2E (End-to-End) Testing
banco di prova del codice in un ambiente con browser integrato e interazione con gli elementi
HTML (input, buttons ecc ecc..).
Il test non conosce la dinamica di funzionamento di componenti e servizi, solo come
usare l' interfaccia e i risultati delle operazioni in essa.
Protractor framework: lo strumento che mette a disposizione infrastruttura e utility per
facilitare la scrittura di test
<page>.e2e-spec.ts : i file e2e-spec contengono i testcase di una pagina da testare
ng e2e: shell command per eseguire i test e2e
protractor.conf.js & tsconfig.e2e.ts: contengono la conf e le opzioni per il run dei test con
protractor
150. DAY FIVE - ANGULAR FUNDAMENTALS
E2E (End-to-End) Testing - Page Object Pattern
Un Page Object (PO) é una classe che descrive l' interfaccia grafica di una pagina
i suoi metodi ritornano generalmente elementi presenti nella pagina
import { browser, by, element } from 'protractor';
export class HomePage {
navigateTo() {
return browser.get('/');
}
getPageTitle() {
return element(by.css('app-home h1.title')).getText();
}
}
le classi PO hanno convenzionalmente nome con suffisso po.ts
151. DAY FIVE - ANGULAR FUNDAMENTALS
E2E (End-to-End) Testing - Testare una pagina
Navigazione sulla pagina da testare (beforeEach)
Interazione con gli elementi visibili in pagina (fill dati form, click pulsanti)
Controllo degli expected values conseguenti (check su etichette, reindirizzamento
pagina, messaggi di avvenuta esecuzione, liste aggiornate)
152. DAY FIVE - ANGULAR FUNDAMENTALS
E2E (End-to-End) Testing - Testare una pagina
Usando la classe PO HomePage si costuisce il test come segue
import { HomePage } from './home.po';
describe('workspace-project Home', () => {
let page: HomePage;
beforeEach(() => {
page = new HomePage();
page.navigateTo(); //navigazione e stato iniziale di pagina
});
it('should display the title of homepage', () => {
expect(page.getPageTitle()).toEqual('Welcome to homepage!');
});
});
153. DAY FIVE - ANGULAR FUNDAMENTALS
E2E (End-to-End) Testing - Testare una pagina
Esempio di test su cambio di pagina
it('Should redirect to the album page when album is clicked', () => {
const album = homePage.getAlbumButton();
album.click();
expect(browser.driver.getCurrentUrl()).toContain('/album');
});
154. DAY FIVE - ANGULAR REFERENCES
Best Practices and Tutorials
Letture:
1. Javascript: The Good Parts
http://shop.oreilly.com/product/9780596517748.do
Sito ufficiale angular: http://angular.io
Organizzazione Progetto: https://medium.com/@michelestieven/organizing-angular-
applications-f0510761d65a