In questa pagina sono raggruppati tutti gli articoli riguardo a Angular & Ionic.

angular ionic

Non si tratta di un manuale o di documentazione ma di un elenco di esempi di codice o mini-guide home-made riguardo allo sviluppo di applicazioni web sviluppate con il framework Anguilar assieme alle librerie Ionic, Redux e NgRx. Si rimanda alla documentazione ufficiale per maggior in formazioni e i dettagli tecnici di ogni argomento.

L'obbiettivo di questi articoli è creare una applicazione web con questi componenti:

  •  framework come base per lo sviluppo di applicazioni web
  • principale linguaggio di programmazione
  •  libreria grafica per lo sviluppo di Web-App ibride
  •  libreria per la gestione dello stato dell'applicazione
  •  libreria per la gestione del workspace
  • libreria per la creazione di app per smartphone

in questo modo sarà possibile creare applicazioni ibride web e app per smartphone basate sulla stessa tecnologia con condivisione di componenti e librerie.

Per la lettura di questi articoli è necessario avere una base di HTML e Javascript, indispensabili per sviluppare siti web e applicazioni con queste tecnologie, si consiglia di aver sempre a portata di click il sito W3C-school per avere sempre disponibile la guida ufficiale. Il linguaggio Typescript è indispensabile per usare al meglio il framework Angular e sarà introdotto con semplici esempi, si rimanda sempre alla documentazione ufficiale per i dettagli tecnici e approfondimenti.

Per la creazione dei progetti e la gestione delle varie fasi di sviluppo fino alla compilazione dei progetti è indispensabile avere a disposizione NPM e NodeJS, rispettivamente gestore delle dipendente e runtime system. Fortunatamente sono facilmente installabili su sistemi Windows e anche su GNU Linux.

Lo sviluppo di stili e siti è possibile con qualsiasi editor di testo anche se è consigliato l'uso di ambiente di sviluppo (IDE) come Visual Studio Code di Microsoft mentre sarà necessario usare Android Studio per lo sviluppo e la creazione dell'app per smartphone, anche in questo caso si rimanda alla documentazione ufficiale.

Typescript_logo_2020

TypeScript è un linguaggio di programmazione open source sviluppato inizialmente da Microsoft come estensione di JavaScript, che aggiunge tipi, classi, interfacce e moduli opzionali al linguaggio tradizionale. Si tratta di un linguaggio tipizzato, ovvero aggiunge le definizioni di tipo statico: i tipi consentono di descrivere la forma di un oggetto, consentendo al compilatore di verificare che il codice sia scritto correttamente evitando errori in fase di esecuzione. 

In questo  articolo sono presentati alcuni semplici esempi di codice per la manipolazione di liste, concetto molto importante e frequente nei progetti web che visualizzano e manipolano dati. Con TypeScript e il framework Angular, è indispensabile conoscere molto bene l'uso delle Arrow-Function e dell'operatore freccia, senza questa conoscenza risulterà impossibile leggere o scrivere codice. Si rimanda alla lettura e alla documentazione ufficiale di mozilla.org per maggiori dettagli.

La sintassi base per definire una variabile in Typescript:

showSpinner: Boolean = false;

Il nome della variabile viene seguito dal due-punti e dal tipo, successivamente è possibile assegnare un valore iniziale. Se si tratta di un tipo non primitivo ma se si tratta di un oggetto la sintassi è simile

export interface AnnotazioniEntity {
id:string|number; // Primary ID
nome:string|null;
}
element : AnnotazioniEntity = {id:1,nome:'Alberto'};

In questo semplice esempio l'inizializzazione avviene tramite la rappresentazione in formato Json, tale modalità è considerata uno standard universale.

Per la gestione delle liste la sintassi è molto simile, per esempio

lista : AnnotazioniEntity[] = [];

Inoltre è importante sapere, perché modalità molto usata, è possibile usare il tipo "any" come jolly per indicare che la variabile può accettare qualsiasi tipo di variabile, per esempio:

list$: Observable<any> = ...;

in questo esempio, nel nome della variabile è stato aggiunto il carattere dollaro "$", questo carattere è tollerato dal compilatore e viene spesso usato per indicare una variabile destinazione di un metodo asincrono, quindi potrebbe non essere valorizzata al caricamento.


Per la gestione delle liste è possibile usare i metodi del linguaggio tra cui: forEach(), indexOf(), slice(), map() e filter(). Questi metodi possono essere usati in combinazione tra loro e permettono di eseguire calcoli e logiche complesse con poche righe di codice, si riportano alcuni esempi:

  • Uno dei metodi più usato è "filter", usato per selezionare solo alcuni elementi da una lista di partenza a seconda di un criterio indicato in un metodo, per esempio volendo filtrare tutti gli elementi con il nome Alberto:
    this.listaAlberto = this.lista.filter ( item => item.nome=='Alberto');
  • Map è molto usato per modificare gli elementi di una lista, per esempio volendo modificare tutti i nomi della nostra lista:
    this.listaModificata = this.lista.map ( item => item.nome='Andrea' ); 
  • Per l'ordinamento degli elementi di una lista è possibile usare il metodo map e indicare la logica di confronto tra due elementi, per esempio volendo ordinare gli elementi una lista per nome
    this.listaVisualizzata$.sort( (el1, el2) => el1.nome > el2.nome ? 1 : -1);
    da notare che in questo caso il linguaggio permette l'operatore di confronto "minore" anche si tratta di stringhe, cosa non permessa in tanti altri linguaggi come Java.
  • Per selezionare un sottoinsieme di una lista si usa il metodo slide indicando l'indice primo e l'ultimo elemento (ricordandosi di che si usa la convenzione che il primo elemento è in indice zero e l'ultimo elemento non viene compreso):
    this.listaPrioritaria = this.listaPersone.slice(0,20);
  • Per eliminare i duplicati da una lista ed ottenere una lista di elementi unici si può usare il tipo Set, per esempio partendo da una lista di persone recuperare l'elenco di tutti i cognomi senza duplicati:
    [...new Set(this.listaPersone.map(e => e.cognome))]
  • Con il metodo reduce è possibile eseguire operazioni su tutti gli elemento di una lista, l'esempio più semplice è calcolare la somma degli elementi di una lista:
    this.listaNumeriPari= [...Array(10).keys()].filter(el=>el%2==0);
    this.totale=this.listaNumeriPari.reduce((sum, element) =>sum+element, 0);
    in questo semplice esempio sono combinati due istruzioni: la prima crea un array con i primi 10 numeri e poi filtra solo i numeri pari, la seconda istruzione esegue la somma con il metodo reduce.
  • Una combinazione di questi metodi può essere usata per calcolare la media mobile di un elenco di valori:
    let elencoAvarageMob = elenco.map( el => { return {x:el.x,
      y:elenco.filter( e => e.x <= el.x)
    .reduce( (sum,el) => sum+el.y ,0 ) / elenco.filter( e => e.x <= el.x).length
    } });
  • Un'altra combinazione di questi metodi è il caso pratico di cercare il valore minimo di una proprietà di una lista di oggetti, per esempio per cercare il più giovane in una lista:
    getGiovane = (lista) => {
    let l=[...listaPersone.map(e => Number(e.eta)+1)].concat([0]);
    return Math.max( l.reduce((a, b) => Math.max(a, b), 0) );
    }

Un simpatico schema che spiega le funzioni principali funzioni disponibili:

L'elenco completo di tutti i metodi usabili è facilmente recuperabile con una ricerca in internet, per esempio nel sito ufficiale di mozilla.org è disponibile una documentazione. 

La gestione delle date è sempre un tema particolare in informatica in quanto ogni linguaggio ha il suo standard e i suoi metodi, Typescript eredita da Javascript la classe Date che rappresenta data e ora assieme:

let date:  Date = new Date();
let date2: Date = new Date("2042-10-16");
let date3: Date = new Date(2018, 08, 31, 17, 23, 42, 11);

Il risultato è un oggetto che se stampato risulterà nel formato

Tue Feb 05 2019 12:05:22 GMT+0530 (IST)

Tutti i metodi della classe Java sono disponibili nella documentazione ufficiale e tutti i metodi disponibili hanno una pagina dedicata. La conversione tra un fuso orario ed un altro è possibile grazie alla combinazioned i metodi, per esempio: 

let dateUTC=new Date("2042-10-16"); // UTC
let dateITA= ""+dateUTC.toLocaleDateString("fr-BE")
+ " " + dateUTC.toLocaleTimeString("fr-BE");

La creazione di un progetto Angular è facilitato dalla procedura guidata messa a disposizione dagli stessi sviluppatori del Framework. Per poter sviluppare è indispensabile avere a disposizione il tool NPM.

La libreria Angular è installabile in un ambiente di sviluppo con il comando:

npm install -g @angular/cli

Successivamente è possibile lanciare la procedura guidata per la creazione di un progetto con il comando:

ng new nomeProgetto

all'interno della procedura guidata vengono richieste le informazioni base del progetto:

  • "add Angular routing": l'abilitazione al routing del framework Angular, di default non viene aggiunto ma conviene sempre aggiungerlo se si vuole creare applicazioni web complessi.
  • "stylesheet format": il formato dei fogli di stile, è possibile scegliere tra Css, sCss, Sass e Less

il processo di creazione del progetto installerà automaticamente anche tutte le dipendenze necessarie per questo motivo il processo può necessitare anche diversi minuti. Al termine del processo è possibile vedere che è stata creata una cartella con nome del progetto e all'interno presenti i file e le cartelle:

  • angular.json: file di configurazione del progetto angular
  • node_modules: cartella creata da NPM con tutte le librerie necessarie
  • package.json: file di configurazione di NPM con la lista di tutte le dipendenze e la lista dei comandi
  • package-lock.json: file di configurazioned i NPM
  • README.md: file README (leggimi) in formato md
  • src: cartella dei sorgenti del progetto
  • tsconfig.app.json: file di configurazione per il compilatore
  • tsconfig.json: file di configurazione per il compilatore

In tutti i progetti Angular, la cartella sorgente "src" ha una struttura ben precisa:

  • app: cartella che contiene i file TypeScript
  • assets: cartella che contiene i file statici dell'applicazione web
  • index.html: file HTML principale, con l'indicazione del header e il richiamo al tag
    app-root che è il tag base di Angular
  • main.js: file javascript dove è possibile definire
  • styles.css: foglio di stile principale dell'applicazione web

All'inteno della cartella "app" sono presenti tutti i file TypeScript, i file principali creati nel progetto base sono:

  • app-routing.module.ts: file di configurazione del routing del modulo "app-root"
  • app.component.css: file Css del componente "app-root"
  • app.component.html: file HTML del componente "app-root"
  • app.component.ts: file TypeScript del componente "app-root" richiamato dalla pagina index
  • app.module.ts: file di definizione del modulo "app-root" del progetto

Maggiori dettagli su questi file sono descritto nell'articolo che parla dei componenti Angular.

Per avviare un qualsiasi progetto base si deve eseguire il comando:

ng serve

e dalla console si può notare come l'applicazione web viene avviata sulla porta 4200 del sistema, la porta e i vari comandi si possono modificare e personalizzare nei vari file di configurazione del progetto.

La compilazione di un progetto può essere avviata con il comando base:

ng build

che va a generare una cartella dist con all'interno i file del progetto, tra cui il file index.html e i file js (javascript) generati dalla compilazione e compressione del codice TypeScript.

Il framework Angular è studiato per funzionare come combinazione di elementi atomici chiamati "component", questi controllano una porzione di schermo denominata "view", ogni componente è formato da una classe TypeScript, un modello HTML, un foglio di stile CSS e, opzionalmente, da una classe spec di testing. Nel sito ufficiale è possibile trovare maggiori dettagli riguardo a questi elementi di un componente, argomento fondamentale da imparare per poter lavorare in progetti Angular. Per creare un nuovo componente all'interno di un progetto è necessario usare il comando:

ng generate component <nome-componente>

La procedura, senza specifici parametri, costruisce la struttura di default di un componente:

  • una cartella chiamata con il nome del componente contenente i quattro file
  • una classe TypeScript in un file con estensione ts con la annotation @Component
  • un file html per il modello grafico del componente chiamato template
  • un file css per gli stili del componente
  • un file di test con estensione spec.ts per gli unit-test della classe Typescript

Il comando prevede alcuni parametri opzionali per modificare il comportamento di default, per esempio per evitare la creazione della cartella con il parametro "standalone", evitare la creazione di un unico file con  il parametro "inline-template" ed è possibile usare un parametro per evitare la creazione della classe specifica per i test "skip-test", un esempio completo di combinazione di questi parametri:

ng generate component <nome-componente-due> 
  --standalone --inline-template --skip-tests

In questo caso il componente è riassunto in unico file TypeScript dove la classe possiede una annotation che definisce il template HTML e gli stili

@Component({
  selector: 'app-component-overview',
  template: '<h1>Hello World!</h1>',
  styles: ['h1 { font-weight: normal; }']
})

questa tecnica è sconsigliata tranne nel caso di componenti di poche righe. La documentazione ufficiale descrive tutte le caratteristiche impostabili nella annotation component. La struttura standard di un componente senza il parametro inline è:

import { Component, OnInit } from '@angular/core';
@Component({
  selector: 'app-nome-componente',
  templateUrl: './nome-componente.component.html',
  styleUrls: ['./nome-componente.component.css']
})
export class NomeComponenteComponent implements OnInit {
  constructor() { }
  ngOnInit(): void { }
}

il componente presenta il nome selector da usare negli altri per invocare il componente. Quando creato, se non specificato diversamente, il componente viene importato anche nel file "app.modules.ts", in questo modo tutti i componenti del modulo potranno importare ed usare il componente-tag creato, senza questa importazione il componente non può essere usato. Se in un progetto sono presenti più moduli deve essere importare in tutti i moduli dove il componente deve essere importato, lo scopo di questa tecnica è creare la struttura ad albero dei componenti:


Projection è la tecnica per sviluppare componenti pensati per incastrarsi in maniera nidificata, esistono tre tipi di utilizzo: semplice, multipla o condizionata.

La tecnica Single-slot content projection prevede che un componente venga compreso in un altro in maniera diretta, usando i due componenti di esempio creati sopra il componente in-line può comprendere quello non in-line usando il tag <ng-content>:

@Component({
  selector: 'app-nome-componente-due',
  template: `<p>nome-componente-due works!</p>
    <p><ng-content></ng-content></p>`,
  styleUrls: ['./nome-componente-due.component.css']
})
export class NomeComponenteDueComponent implements OnInit {
  constructor() { }
  ngOnInit(): void { }
}

Per richiamare il secondo componente nel primo bisogna aggiungerlo nel template:

<p>nome-componente works!</p>
<app-nome-componente-due>
  contenuto del uno passato al componente due
</app-nome-componente-due>

La tecnica multipla e la tecnica condizionale sono ben descritti con esempi nel sito ufficiale, queste tecniche sono molto usate nei progetti proprio nella filosofia della struttura ad albero dei componenti, la gestione di dati e degli eventi vengono gestiti con le annotation Input/Output e gli eventEmitter descritti nei prossimi articoli.

In Angular, un template è un frammento di un'interfaccia grafica utente (UI), spesso in italiano viene confuso con il nome "modulo" ma conviene abituarsi ad usare il termine originale in inglese. I template sono scritti in HTML e all'interno è possibile utilizzare una sintassi speciale per sfruttare molte delle funzionalità di Angular che estende la sintassi HTML, questa tecnica permette di creare contenuti dinamici modificando le proprietà del documento (DOM). La sintassi HTML deve essere valida e il fratello non deve includere tag base come <html> e <body> visto che sono gestiti dal framework.

  • La prima tecnica, chiamata Interpolation, prevede l'uso dei limitatori {{ e }} per visualizzare variabili o richiamare metodi della classe corrispondente al template, per esempio se in un template è presente una proprietà è possibile visualizzare la variabile nel template. Per esempio <div >Benvenuto {{name}}</div>
  • La seconda tecnica, chiamata Template statements, permette di gestire eventi nei template richiamando metodi nella classe corrispondenti, a qualsiasi oggetto DOM è possibile associare un evento con le parentesi tonde e indicare il nome del metodo richiamato. Per esempio <button type="button" (click)="changeName()" 
  • La terza tecnica, chiamata Property binding, permette di gestire proprietà e oggetti DOM da valori o metodi della classe richiamando il valore con le parentesi quadre. Per esempio <button type="button"[disabled]="isDisabled"
  • La quarta tecnica, chiamata Event binding, permette di gestire eventi specifici come l'inserimento dei tasti tramite sottoeventi con metodi specifici. Per esempio e(keydown.shift.t)="onKeydown($event)"
  • Altre tecniche come le direttive input-output e gli eventEmitter saranno introdotti in specifici articoli.
Angular poi mette a disposizione alcune proprietà chiave per la gestione di alcuni casi specifici molto frequenti:
  • ndClass: utlizzata per la gestione delle classi in maniera dinamica usando le operazioni ternarie o metodi della classe corrispondente. Per esempio <p [ngClass]="isDisabled ? 'textRed' : 'textGreen' ">
  • *ngFor: utile per gestire cicli in maniera dinamica usando come base un elenco presente nella classe del componente. Per esempio <span *ngFor="let figlio of lista">{{figlio}} </span>
  • *ngIf: utile per gestire la visibilita di oggetti DOM con una condizione, spesso viene usata una proprietà della classe del componente. Per esempio <div *ngIf="!isDisabled">...</div>

Tutte queste tecniche sono molto usate nei progetti e devono essere ben conosciute in quanto permettono di separare le logiche presenti nelle classi e la rappresentazione grafica del template. Un semplice esempio completo con queste tecniche in un template in-line:

import { Component, OnInit } from '@angular/core';
@Component({
  selector: 'app-nome-componente-due',
  template: `<div >
    Benvenuto {{name}}
    <button type="button" (click)="changeName()" [disabled]="isDisabled">
      Cambia nome</button>
    <div *ngIf="!isDisabled">Clicca il bottone per scoprire</div>
    <input (keydown.shift.t)="onKeydown($event)" />
    <div [ngSwitch]="name" [ngClass]="isDisabled ? 'textRed' : 'textGreen' ">
      <div *ngSwitchCase="'Alberto Nao'" >Fratello minore</div>
      <div *ngSwitchCase="'Andrea Nao'" >Fratello maggiore
        <br />figli: <span *ngFor="let figlio of lista">{{figlio}} </span>
      </div>
    </div>
    <div><ng-content></ng-content></div>
  </div>`,
  styleUrls: ['./nome-componente-due.component.css']
})
export class NomeComponenteDueComponent implements OnInit {
  constructor() { }
  name = 'Alberto Nao';
  isDisabled=false;
  lista=['Alice','Elena','Achille','Ettore'];
  ngOnInit(): void { }
  changeName(){
    this.name="Andrea Nao";
    this.isDisabled=true;
  }
  onKeydown(event:any){// console.log(event)
    console.log( "E' stato premuto la lettera "+event.key+" " );
  }
}

La documentazione ufficiale è ricca di esempi e descrive molto bene tutte le tecniche utilizzabili nei template Angular.

Il framework Angular è studiato per essere modulato formato da tanti componenti che condividono informazioni e dati tra di loro, nel caso di dati dinamici sono previsti alcuni decorator studiati per semplificare la vita dei programmatori. Prima di tutto bisogna pensare di essere in strutture del tipo annidato: un componente contiene uno o più component. Se il padre volesse inviare un dato dinamico non può usare la tecnica del "Single-slot content projection" o simili in quanto funzionano solo con contenuti statici.

La direttiva di input permette di inviare informazioni dal padre al figlio, per esempio avendo due componenti e volendo passare un valore numerico da un padre ad un figlio:

@Component({
  selector: 'app-padre',
  template: `<app-figlio [valoreF]="valoreP"></app-figlio>
    <p (click)="addNelPadre()">Aggiungi uno</p>`,
  styles: [ ]
})
export class PadreComponent {
  valoreP : number =0; 
  ngOnInit(): void { this.valoreP=42; }
  addNelPadre(){ this.valoreP++;}
} 
////////////////////////////////////////////////////
Component({
  selector: 'app-figlio',
  template: `<p>Il valore è {{valoreF}}</p>`,
  styles: [ ]
})
export class FiglioComponent {
  @Input() valoreF : number | undefined;
}

nell'esempio è stato inserito anche un metodo nel padre per poter modificare il valore (nel padre) e constatare che il valore viene propagato dinamicamente anche nel figlio.

La tecnica per inviare dati ed eventi da un componente ad un genitore prevede l'uso della direttiva @Output e l'uso degli EventEmitter nel caso ci sia la necessità di eseguire un evento nel componente superiore scatenato da un evento del figlio padre, per esempio un bottone nel figlio per eseguire un metodo nel componente padre con la possibilità di far transitare anche un valore (stringa):

@Component({
  selector: 'app-padre',
  template: `<app-figlio [valoreF]="valoreP" 
    (figlioEmitter)="eventoNelFiglio($event)"></app-figlio>
    <p (click)="addNelPadre()">Aggiungi uno</p>`,
  styles: [ ]
})
export class PadreComponent {
  valoreP : number =0; 
  ngOnInit(): void { this.valoreP=42; }
  addNelPadre(){ this.valoreP++;}
  eventoNelFiglio(value : string){this.valoreP+=Number(value);}
} 
////////////////////////////////////////////////////
@Component({
  selector: 'app-figlio',
  template: `<p>Il valore è {{valoreF}}</p>
    <label>Add <input #inputF></label>
    <button (click)="addValue(inputF.value)">
    Add to parent's value</button>`,
  styles: [ ]
})
export class FiglioComponent {
  @Input() valoreF : number | undefined;
  @Output() figlioEmitter = new EventEmitter<string>();
  addValue(value: string){
    this.figlioEmitter.emit(value);
  }
}

Questa tecnica prevede anche l'uso di @Input e @Output assieme, nell'esempio appena introdotto il figlio ha due proprietà diverse (una per input e una per output), è possibile inoltre evitare di dover aggiungere le annotation nel codice ma è possibile dichiarare l'elenco delle proprietà coinvolte nella dichiarazione dei meta-dati del componente aggiungendo anche un alias in modo che proprietà del padre e del figlio abbiano nomi diverse:

@Component({
  selector: 'app-figlio',
  template: `<p>Il valore è {{valore}}</p>
    <label>Add <input #inputF></label>
    <button (click)="addValue(inputF.value)">
    Add to parent's value</button>`,
  styles: [ ],
  inputs: ['valore: valoreF'], // propertyName:aliasInParent
  outputs: ['evento: figlioEmitter']
})
export class FiglioComponent {
  valore : number | undefined;
  figlioEmitter = new EventEmitter<string>();
  addValue(value: string){
    this.evento.emit(value);
  }
}

La documentazione ufficiale è sempre il punto di riferimento di questa tecnica che è da usare ogni volta che è necessario inviare o scambiare dati dinamici tra componenti in un progetto Angular.

La gestione di form e inserimento dati è sempre un argomento molto delicato e complesso visto che ogni framework e ogni linguaggio gestire l'inserimento di dati in maniera differente. Su Angular esistono diversi modi più o meno ufficiali e più o meno efficienti, qui saranno esposti diversi modi di gestione degli input usabili a seconda delle diverse esigenze.  Il metodo più semplice è gestire il valore con il metodo change, così da avere un metodo per la gestione del valore, l'esempio classico è:

lista: Person[]=[{id:'1',nome:'Alberto'},{id:'2',nome:'Andrea'},...]
selezionato: Person=this.lista[0];
cambia($event: any): void { 
  let input = $event.target; 
  this.selezionato=this.lista.filter ( e => e.id===input.value)[0];
}
...
<select (change)="cambia($event)">
  <option *ngFor="let el of lista;" 
    value="{{el.id}}">{{el.nome}} ({{el.id}})</option>
</select>
<span>Elemento selezionato: {{selezionato.nome}}</span>

questo metodo potrebbe sembrare arcaico e da evitare, in realtà è molto utile quando un input deve scatenare un evento senza l'uso di bottoni submit o simili, l'esempio più classico è un form per la selezione e il caricamento di un file il cui metodo di gestione può essere:

fileUploaded: File;
uploadListener($event: any): void { //console.log("uploadListener");
  this.fileUploaded = $event.target.files[0]; 
  let readFile = new FileReader(); 
  readFile.onload = (e) => { 
    //load data & next step
  }
  readFile.readAsArrayBuffer(this.fileUploaded); 
}

Il metodo più semplice per creare forms composti è usare la tecnica del template-driven ben documentata nel sito ufficiale, prevede l'uso delle parole chiave NgModel e NgForm. Prima di tutto bisogna definire una classe che rappresenta il modello dei dati inseriti, per esempio:

class Person {
  constructor(
    public id: string,
    public nome: string,
    public age?: number
  ) { }
}

Nella classe è possibile definire una proprietà modello con dei valori predefiniti e un metodo per la gestione del submit, nell'esempio viene solo gestita la visibilità del form:

ngOnInit() {
  this.newHero();
}
formModel : Person ;
newHero() {
  this.formModel = new Person('4','Daniele',42 );
}
submitted = false;
onSubmit() { 
  this.submitted = true; 
}

Nel template bisogna usare ngForm per creare un riferimento e ngModel per ogni input per il recupero e la gestione dei valori, la validità dei form viene gestita grazie alle regole HTML: nell'esempio il nome è obbligatorio e il bottone si disabilità automaticamente quando il form diventa invalido a seconda delle regole indicate nel form:

<div [hidden]="submitted">
  <form #personForm="ngForm" (ngSubmit)="onSubmit()">
    <input type="text" class="form-control" id="name" 
      required [(ngModel)]="formModel.nome" name="nome" />
    <div>Nome inserito {{formModel.nome}}</div>
    <button type="button" (click)="newHero();">New Hero</button>
    <button type="submit" [disabled]="!personForm.form.valid">Submit</button>
  </form>
</div>

Questa tecnica è molto usata quando le regole di validazione sono semplici, gli input sono numericamente poche e quando il comportamento di un form è semplice senza particolarità.


La tecnica più evoluta e usata nel mondo è la creazione dei form reattivi (traduzione dell'inglese reactive-forms), con questa tecnica è possibile creare una sincronia attiva tra oggetto nella classe e valore nel template, nella documentazione è definita come il metodo ufficiale per creare form in Angular. Per poterla attivare bisogna includere nel modulo specifico:

import { ReactiveFormsModule } from '@angular/forms';
...
@NgModule({
  imports: [
    // other imports ...
    ,ReactiveFormsModule
  ],
});

Questa libreria/modulo standard di Angular prevedo l'uso della classe FormControl nel package standard angular/forms che permette di collegare una proprietà nella classe ad un oggetto nel template proprio con la proprietà formControl. Nella classe per esempio è possibile definire una proprietà e un metodo per modificarne il valore

import { FormControl } from '@angular/forms';
...
nomeReattivo = new FormControl('');
updateNameReattivo() { this.nomeReattivo.setValue('Alberto'); }

Nel template è possibile creare il collegamento tra oggetto nella classe e tag di tipo input con una proprietà del framework Angular, inoltre sempre possibile creare recuperare il valore in maniera standard e creare eventi

Nome reattivo:<input id="name" type="text" [formControl]="nomeReattivo">
<div>Nome reattivo inserito: {{ nomeReattivo.value }}</div>
<button type="button" (click)="updateNameReattivo()">Update nome reattivo</button>

Questa tecnica è molto veloce da implementare se il numero di campi è limitato, nel caso di form con diversi campi potrebbe essere noioso e sconveniente usare questa tecnica infatti esiste la possibilità di creare un "gruppo" di elementi di tipo FormControl: è necessario creare un oggetto di tipo FormGroup contenente la lista degli input definiti come nell'esempio precedente:

import { FormGroup, FormControl } from '@angular/forms';
import { Validators } from '@angular/forms';
...
personFormGroup = new FormGroup({
  firstName: new FormControl('', 
    [ Validators.required, Validators.minLength(3) ]),
  repeatName: new FormControl('', [this.comparisonValidator ]),
  mail: new FormControl('', 
    Validators.pattern("[a-z0-9._%+-]+@[a-z0-9.-]+.[a-z]{2,3}$") )
});
setValueFirstName(first){
  this.personFormGroup.controls['firstName'].setValue(first);
}
onSubmitpPersonGroup() {
  // TODO: Use EventEmitter with form value
  console.log(this.personFormGroup.value);
}

Nel template non si deve inserire una proprietà per ogni input ma si deve agganciare l'intero form al gruppo definito nella classe.

<form [formGroup]="personFormGroup" (ngSubmit)="onSubmitpPersonGroup()">
  <label for="first-name">First Name: </label>
  <input id="first-name" type="text" formControlName="firstName" required />
  <label for="last-name">Repeat Name: </label>
  <input id="last-name" type="text" formControlName="repeatName" />
  <label for="last-name">E-Mail: </label>
  <input id="last-name" type="text" formControlName="mail" />
  <button type="submit" [disabled]="!personFormGroup.valid">Submit personFormGroup</button>
</form>

In questo semplice esempio è possibile notare che sono state introdotte delle regole di validazione nella definizione del FormGroup, la tecnica di form-reattivi permette di definire per ogni campo una regola di validazione che viene validato in maniera reattiva. La documentazione ufficiale descrive tutte le regole previste dal pacakge standard di angular ma è possibile definire regole di validazione personalizzate, per esempio per validare che l'utente abbia inserito correttamente due volte lo stesso valore nei due campi:

comparisonValidator(control: AbstractControl) : ValidationErrors{ 
  if (!control.parent)
    return;
  const name=control.parent.value.firstName;
  const isValid=control.value===name;
  return isValid ? null : { 'myCustomError': 'This value is invalid' }; 
}

Nel template è possibile gestire la visualizzazione di messaggi a sconda se un errore di validazione è presente o meno, usando l'esempio di validazione dei nomi inseriti due volte è possibile visualizzare un messaggio se i nomi inseriti non coincidono:

<span [hidden]="!personFormGroup.get('repeatName').errors?.myCustomError">
  I nomi devono coincidere</span>

Un esempio funzionante è disponibile al solito repository:

https://github.com/alnao/AngularReactNodeExamples/tree/master/AngularDatasetsFilms

Esiste una ulteriore tecnica per gestire l'inserimento dei dati e il passaggio dei dati dal template alla classe corrispettiva: questa tecnica prevede la definizione di un riferimento in un oggetto nel DOM che può essere usata in altri punti del template, la documentazione ufficiale è molto chiara a riguardo e prevede l'uso del carattere  per la definizione di questi riferimenti, un semplice esempio di template che usa questa tecnica è:

<input #phone placeholder="phone number" />
<button type="button" (click)="callPhone(phone.value)">Call</button>

Questa tecnica è considerata deprecata da molti anche se, essendo stata molto usata in passato, si trova molto spesso nei progetti ed è ancora usata dai programmatori per la sua semplicità d'uso.

Il framework Angular mette a disposizione alcune tecniche per la gestione dei dati nei template, si tratta di tecniche per la gestione della visualizzazione dei dati ma anche tecniche per la gestione dei dati inseriti dall'utente senza l'uso dei form. In questo articolo saranno comprese le tecniche molto usate che non prevedono l'uso dei form e delle variabili, tecniche già esposte in precedenti articoli.

La tecnica più semplice è l'uso del carattere  detto anche Pipe (in inglese traduzione della parola tubo), questa tecnica viene descritta nel sito ufficiale e prevede la definizione di semplici espressioni che accettano un valore in input e ritornano il valore trasformato, sono molto usate perché possono essere usate nei template per trasformare e formattare i dati senza dover modificare il valore originale, un esempio semplice di utilizzo è la formattazione delle date che spesso nei servizi/webService sono nel formato standard json/javascript ma nei template è necessario visualizzarlo nel formato dd/mm/yyyy o simili.

{{valueDate | date: 'dd/MM/yyyy'}}

Le più comuni espressioni pipe previste dal framework sono: DatePipe, UpperCasePipe, LowerCasePipe, CurrencyPipe, DecimalPipe, PercentPipe.

E' possibile scrivere espressioni personalizzate, per esempio per definire una espressione per eseguire l'esponenziale bisogna definire una classe che implementi il metodo di trasformazione:

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'exponentialStrength'})
export class ExponentialStrengthPipe implements PipeTransform {
  transform(value: number, exponent = 1): number {
    return Math.pow(value, exponent);
  }
}

E poi è possibile usare l'espressione nei template

{{2 | exponentialStrength: 10}}

La documentazione ufficiale mette a disposizione diversi esempi semplici e spiegazioni complete riguardo a questo argomento. L'esempio completo dell'esponenziale infatti è completato nella documentazione ufficiale con l'uso delle variabili è l'uso del ngModel:

@Component({
  selector: 'app-power-boost-calculator',
  template: `
    <h2>Power Boost Calculator</h2>
    <label for="power-input">Normal power: </label>
    <input id="power-input" type="text" [(ngModel)]="power">
    <label for="boost-input">Boost factor: </label>
    <input id="boost-input" type="text" [(ngModel)]="factor">
    <p>
      Super Hero Power: {{power | exponentialStrength: factor}}
    </p>
  `,
  styles: ['input {margin: .5rem 0;}']
})
export class PowerBoostCalculatorComponent {
  power = 5;
  factor = 1;
}

Un'altra applicazione delle pipe è realizzare filtri sugli elenchi nei cicli ngFor, per esempio per filtrare i primi 50 elementi di una lista si può usare la espressione standard slice:

<li *ngFor="let elemento of listaCompleta | slice:0:50 ; let i = index;">
...
</li>

Ma è possibile usare anche slice personalizzare definire da classi specifiche, per esempio per eseguire un filter su una lista si può definre una espressione personalizzata:

@Pipe({ name: 'flyingHeroes' })
export class FlyingHeroesPipe implements PipeTransform {
  transform(allHeroes: Hero[]) {
    return allHeroes.filter(hero => hero.canFly);
  }
}

E nel template si può richiamare la espressione

<li *ngFor="let hero of (heroes | flyingHeroes)">
  {{hero.name}}
</li>

Questa tecnica è usata moltissimo dai programmatori anche per gestire gli oggetti json: in fase di sviluppo è necessario trasformare oggetti json in stringa per visualizzare l'intero oggetto in un template, nativamente Angular non visualizza gli oggetti complessi mentre l'uso del pipe json permette di avere a video la forma completa di un oggetto, la documentazione ufficiale spiega che è usato per convertire un valore nel suo formato json rappresentabile in pagina. L'esempio semplice di questo componente:

@Component({
  selector: 'json-pipe',
  template: `<div>
    <p>Without JSON pipe:</p><pre>{{object}}</pre>
    <p>With JSON pipe:</p><pre>{{object | json}}</pre>
  </div>`
})
export class JsonPipeComponent {
  object: Object = {foo: 'bar', baz: 'qux', nested: 
    {xyz: 3, numbers: [1, 2, 3, 4, 5]}};
}

Il framework mette a disposizione anche il pipe di tipo AsyncPipe che verrà introdotto nell'articolo specifico che palerà della gestione dei servizi e delle funzioni asincrone.

La programmazione di tutte le applicazioni web attuali si basa sul paradigma che prevede il caricamento dei dati in maniera asincrona rispetto al caricamento delle pagine e dei componenti grafici: prima si carica la pagina e poi si caricano i dati, questa tecnica permette di creare siti "apparentemente" molto veloci e dinamici slegando le componenti grafiche dalle componenti dei dati. Angular prevede questa separazione separando completamente il codice typescript e i template che rappresentano le componenti grafiche.

Nei progetti Angular oltre alla separazione classe e template si aggiunge un ulteriore tecnica: i service, si tratta di componenti con una classe specializzata: eseguire chiamate a servizi esterni o altri componenti in maniera asincrona, richiamabili dai componenti grafici con la tecnica del dependency-injection, si rimanda alla documentazione ufficiale per approfondimenti riguardo a questa tecnica.

Sempre la documentazione ufficiale descrive un semplice esempio di service, come semplice classe typescript con la annotation Injectable che esegue dei log:

@Injectable()
export class LoggerService {
  log(msg: any) { console.log(msg); }
  error(msg: any) { console.error(msg); }
  warn(msg: any) { console.warn(msg); }
}

Questa tenica permette di iniettare (traduzione del termine Inject) nel costruttore del componente grafico, richiamando successivamente il service come se fosse una proprietà dell'oggetto:

export class HeroService {
  private heroes: Hero[] = [];
  constructor(private backend: BackendService, 
    private logger: LoggerService) { }
  getHeroes() {
    this.backend.getAll(Hero).then( (heroes: Hero[]) => {
      this.logger.log(`Fetched ${heroes.length} heroes.`);
      this.heroes.push(...heroes); // fill cache
    });
    return this.heroes;
  }
}

Angular suggerisce di distingue i componenti template dai servizi per aumentare la modularità, efficienza e la riusabilità, cercando di definire applicazioni che rispettano il paradigma MVC.


La tecnica dei service è combinata con le tecniche di asincronia per creare componenti dinamici e veloci, principalmente esistono due tipi di tecniche per gestire i servizi asincroni:

  • una Promise è la gestione di un evento di tipo non sincrono, nel codice si invia una richiesta e si definisce il comportamento alla risposta e la gestione dell'errore. un Observable è una sequenza di eventi inviato ad una funzione di callback simile al concetto di Stream
da notare che questa distinzione spesso viene fraintesa o completamente dimenticata dai programmatori che "troppo" spesso le confondono.

Un semplice esempio di utilizzo della tecnica Promise è la classica chiamata ad un servizio API rest in maniera asincrona, qui viene richiamato il servizio Wiki per recuperare

import { Injectable } from '@angular/core';
import { URLSearchParams, Jsonp } from '@angular/http';
@Injectable()
export class WikipediaService {
  constructor(private jsonp: Jsonp) {}
  search (term: string) {
    var search = new URLSearchParams()
    let endoint="http://en.wikipedia.org/w/api.php?callback=JSONP_CALLBACK";
    search.set('action', 'opensearch');
    search.set('search', term);
    search.set('format', 'json');
    return this.jsonp.get(endpoint, { search }).toPromise()
      .then((response) => response.json()[1]);
  }
}

e il componente può richiamare il service indicando un metodo per la gestione dell'esito con "then" e la gestione di un eventuale errore, per esempio:

@Component({
selector: 'my-app',
template: `
  <div>
    <h2>Wikipedia Search</h2>
     <input #term type="text" (keyup)="search(term.value)">
    <ul><li *ngFor="let item of items">{{item}}</li></ul>
  </div>
`
})
export class AppComponent {
  items: Array<string>;
  constructor(private wikipediaService: WikipediaService) {}
  search(term) {
    this.wikipediaService.search(term)
    .then(items => this.items = items)
    .error(mes => console.log(mes) );
  }
}

maggior dettagli di questo esempio possono essere trovati alla documentazione. Ovviamente il metodo definite di callBack non è necessariamente una sola istruzione ma può essere un blocco di codice complesso, per esempio un metodo per scaricare un file di testo ritornato da una API

downloadFile(e : any, el: any){ 
  axios.get(this.urlLista +"?fileName="+el.fileName,this.getConfigHttp()
  ).then( (response:any) => {
    const lista : any[]= response.data
    const lista2 : any[]=[]
    lista.forEach(element => {
      lista2.push(element + this.stringaAcapo);
    });
    var blob = new Blob(lista2, {type: 'text/txt' })
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = el.fileName +".csv";
    a.click();
    window.URL.revokeObjectURL(url);
    a.remove();
  }).catch( e => { 
      console.log(e); alert("Impossibile scaricare il file"); 
  });
}

Il framework Angular mette disposizione dei programmatori un operatore specifico per la gestione degli oggetti asincroni: se un oggetto viene definito come asincrono

greeting: Promise<string>|null = null;

se questo venisse usato nei template senza specifiche, verrebbe generato un errore in fase di esecuzione perchè l'oggetto non sarebbe valorizzato quindi è stato introdotto il AsyncPipe, nella documentazione ufficiale viene indicato come il gestore di valori asincroni di un Observable o una Promise e restituisce l'ultimo valore emesso: quando viene emesso un nuovo valore, viene assegnato il nuovo valore nel template mentre quando il componente viene distrutto, la pipe asincrona annulla automaticamente la sottoscrizione per evitare potenziali perdite di memoria.

Tecnicamente questa è una comune pipe già descritta in un articolo specifico:

<span>Wait for it... {{ greeting | async }}</span>


Un semplice esempio di Observable è l'uso di setInterval e l'uso di next per la gestione dello "stream" di tipo Observable:

@Component({
selector: 'async-observable-pipe',
template: '<div><code>observable|async</code>: Time: {{ time$ | async }}</div>'
})
export class AsyncObservablePipeComponent {
  time$ = new Observable<string>((observer: Observer<string>) => {
    setInterval(() => observer.next(new Date().toString()), 1000);
  });
}

La documentazione ufficiale consiglia che le proprietà di questo tipo abbiano il simbolo $ prima o dopo il nome così da poterle identificare velocemente. Per ogni oggetto di questo tipo si possono/devono gestire tre metodi:

numbers$.subscribe({
  next: value => console.log('Observable emitted the next value: ' + value),
  error: err => console.error('Observable emitted an error: ' + err),
  complete: () => console.log('Observable emitted the complete notification')
});

i cui nomi sono molto esplicativi del loro utilizzo. Si rimanda alla documentazione ufficiale per maggiori dettagli riguardo alla libreria RxJS e agli EventEmitter che sono sistemi di gestione avanzati di servizi asincroni.


Sempre la sotto-libreria RxJS mette a disposizione un metodo specifico forkJoin che permette di chiamare più sevice di tipo Obserable in parallelo e viene eseguito un blocco di codice di rollback quando tutti gli obsersable sono completate, la definizione del metodo è

export declare function forkJoin<A, B, C>(
  sources: [ObservableInput<A>, ObservableInput<B>, ObservableInput<C>]
): Observable<[A, B, C]>;

cioè questo metodo accetta più Obserable in input e ritorna un unico oggetto di tipo Obserable, in questo modo è possibile gestire il parallismo delle chiamate a service. Un esempio di utilizzo di questa tecnica è:

const $flussi=this.elencoService.get("flussi");
const $out=this.elencoService.getStaging("outgoing");
const $in=this.elencoService.getStaging( "incoming")
forkJoin([$flussi, $out,$in]).subscribe(([returnFlussi, returnOut, returnIn]) => {
  console.log("Risposta di tutti forkJoin");
  this.caricaEsiti(returnFlussi, returnOut, returnIn);
},error => {alert("Errore");console.log(error);});

In tutte le applicazioni web di tipo single-page il tema della navigazione tra componenti è un aspetto che deve sempre essere analizzato attentamente: la applicazione deve impostare quali "rotte" sono associate ai componenti. Il framework Angular ha in sistema di gestione della navigazione tra componenti detto routing che viene configurato alla creazione di un progetto e si basa sulla tecnica dichiarativa: nella classe di configurazione dell'applicazione si deve finire un "provider di rotte" e questo elenco deve essere importato nella classe che dichiara il modulo o nella classe globale dell'applicazione:

@NgModule({
  imports: [
    BrowserModule, FormsModule,
    RouterModule.forRoot(appRoutes)
  ],
  ...

Nel file principale dell'applicazione il componente principale deve essere sostituito dal tag:

<router-outlet></router-outlet>

e le rotte vengono definite come elenco in un file specifico:

import { Routes } from '@angular/router';
const appRoutes: Routes = [
  { path: 'first-component', component: FirstComponent },
  { path: 'second-component', component: SecondComponent },
  { path: '', redirectTo: '/first-component', pathMatch: 'full' }, // redirect to `first-component`
  { path: '**', component: PageNotFoundComponent }, // route for a 404 page
];

La documentazione ufficiale descrive in maniera chiara e completa tutte le proprietà possibili messe a disposizione del framework per la definizione delle rotte e del loro comportamento. Per la navigazione tra componenti è possibile usare i classici tag link di HTML con riferimento alle rotte definite:

<nav>
  <a class="button" routerLink="/first-component">First</a> |
  <a class="button" routerLink="/second-component">Second</a>
</nav>

Il comportamento delle rotte possono essere personalizzate, come descritto nella guida ufficiale, la tecnica più usata è la definizione rotte parametriche come descritto nel sito ufficiale: questa tecnica permette di creare rotte legate a componenti che necessitano di parametri, il classico esempio è un componente che visualizza il dettaglio di un elemento che necessita l'identificato dell'elemento da visualizzare, la rotta deve essere definita:

const heroesRoutes: Routes = [
  { path: 'heroes', component: HeroListComponent },
  { path: 'hero/:id', component: HeroDetailComponent }
];

Usando questa tecnica, la rotta creata dal framework sarà del tipo:

localhost:4200/hero/15

Nel componente è possibile recuperare il valore del parametro da un oggetto contenente la mappa dei parametri, componente messo a disposizione dal framework del tipo ActivatedRoute e iniettabile nel costruttore del componente come fosse un servizio:

constructor(private route: ActivatedRoute,private router: Router) {}
ngOnInit() {
  this.hero$ = this.route.paramMap.pipe(
    switchMap((params: ParamMap) =>
    this.setParametro(params.get('id')!))
  );
}

Si rimanda alla documentazione ufficiale per maggior in formazioni sul concetto di mappa dei parametri.


Per la gestione delle rotte nei componenti, è possibile creare collegamenti alle rotte parametriche impostando dinamicamente i valori, per esempio:

<a [routerLink]="['/hero', hero.id]">

In alternativamente è possibile gestire il routing anche nel codice typescript dei componenti grazie alla classe Router:

gotoHeroes(heroId) { //this.router.navigate(['/heroes']);
  this.router.navigate(['/hero', { id: heroId }]);
}

Esistono molte altre possibilità nell'uso delle rotte come la gestione asincrona della navigazione e la gestione delle autorizzazioni degli utenti in fase di navigazione, in futuri articoli alcuni di questi argomenti saranno approfonditi ma si rimanda sempre al sito ufficiale come fonte principale di informazioni, si consiglia anche di analizzare l'esempio live funzionante che racchiude esempi di tutte queste tecniche.

Nei progetti Angular i Moduli sono gruppi di componenti di una applicazione, il raggruppamento permette di gestire le importazioni di altri moduli e la gestione del comportamento i unico punto dichiarativo dove vengono elencati i componenti, altri moduli importati e i providers (come gli interceptor), per esempio nella applicazioni presentate in altri articoli è stato creato un modulo di default dalla procedura guidata di creazione dei progetti:

@NgModule({
  declarations: [
    AppComponent,
    FilmsListComponent,
    FilmDetailComponent,
    LoginComponent,
  ],
  imports: [
    BrowserModule, 
    ReactiveFormsModule,
    AppRoutingModule,
    HttpClientModule
  ],
  providers: [{
    provide: HTTP_INTERCEPTORS, 
    useClass: AuthInterceptorServiceService,
    multi: true
  }],
  bootstrap: [AppComponent],
  schemas: [CUSTOM_ELEMENTS_SCHEMA,NO_ERRORS_SCHEMA]
}) export class AppModule { }

in questo caso tutti i componenti non devono importare i moduli dichiarati nella sezione imports e quindi risulta molto più snello e semplice.

Tuttavia nei progetti di grandi dimensioni questa tecnica presenta alcune limitazioni: la sezione dichiarativa può diventare molto grande e complessa, inoltre tutti i moduli usati nella applicazione risultano condivisi tra tutti i componenti anche quelli che non li usano. Per risolvere questo problema esisono due strade: dichiarare diversi moduli separando i componenti e gli import a seconda delle necessità rendendo molto snello il codice ma anche in questo caso si richiesta il disordine causato dal proliferare di classi di questo tipo.

La tecnica alternativa più usata è l'uso dei componenti con la caratteristica standalone, questa permette di definire componenti che importano in autonomia i moduli senza dover dichiarare l'elenco dei moduli nella classe generica. Per creare componenti di questo tipo si può usare la sintassi

ng g c component_name --standalone

Un semplice esempio mostra come la sintassi implementa questa tecnica:

@Component({
  standalone: true, 
  selector: 'photo-gallery',
  // an existing module is imported directly into a standalone component
  imports: [MatButtonModule],
  template: `
...
  <button mat-button>Next Page</button>
`,
})
export class PhotoGalleryComponent {
  // logic
}

In questo semplice esempio presentato nella documentazione ufficiale  è possibile vedere come aggiungendo la proprietà standalone si può aggiungere una sezione imports specifica nella dichiarazione delle annotation del componente. Sempre nel sito ufficiale esiste anche una pagina specifica dedicata alla migrazione da componenti modulari a componenti standalone.

È online la nuova versione del sito con contenuti aggiornati. Nessun articolo e nessun contenuto di questo sito è stato creato con IA o generatori automatici di testi ma tutto è stato scritto con molta pazienza personalmente da Alberto Nao. Tutto il codice presente nel sito Tutti gli esempi di codice nel sito sono coperti da

I contenuti di AlNao.it potrebbero avere inesattezze o refusi. Non potrà in alcun caso e per qualsiasi motivo essere ritenuta responsabile di eventuali imprecisioni ed errori né di danni causati. Il sito web e tutte le informazioni ed i contenuti in esso pubblicati potranno essere modificati in qualsiasi momento e di volta in volta e senza preavviso. Poiché ogni materiale sarà scaricato o altrimenti ottenuto attraverso l’uso del servizio a scelta e a rischio dell’utente, ogni responsabilità per eventuali danni a sistemi di computer o perdite di dati risultanti dalle operazioni di scarico effettuato dall'utente, ricade sull'utente stesso e non potrà essere imputata ad AlNao.it che declina ogni responsabilità per eventuali danni derivanti dall'inaccessibilità ai servizi presenti sul sito o da eventuali danni causati da virus, file danneggiati, errori, omissioni, interruzioni del servizio, cancellazioni dei contenuti, problemi connessi alla rete, ai provider o a collegamenti telefonici e/o telematici, ad accessi non autorizzati, ad alterazioni di dati, al mancato e/o difettoso funzionamento delle apparecchiature elettroniche dell’utente stesso.

AlNao.it ha adottato ogni possibile accorgimento al fine di evitare che siano pubblicati, nel sito web, contenuti che descrivano o rappresentino scene o situazioni inappropriate o tali che, secondo la sensibilità degli utenti, possano essere ritenuti lesivi delle convinzioni civili, dei diritti umani e della dignità delle persone, in tutte le sue forme ed espressioni. In ogni caso non garantisce che i contenuti del sito web siano appropriati o leciti in altri Paesi, al di fuori dell’Italia. Tuttavia, qualora tali contenuti siano ritenuti non leciti o illegali in alcuni di questi Paesi, ti preghiamo di evitare di accedere al nostro sito e ove scegliessi, in ogni caso, di accedervi, ti informiamo che l’uso che deciderai di fare dei servizi forniti dal sito sarà di tua esclusiva e personale responsabilità. L’utente sarà esclusivo responsabile della valutazione delle informazioni e del contenuto ottenibile mediante il sito web. Il sito web e tutte le informazioni ed i contenuti in esso pubblicati potranno essere modificati in qualsiasi momento e di volta in volta e senza preavviso.

Le pagine di questo sito sono protette dal diritto d’autore (copyright), in particolare a norma della legge sul diritto d’autore e il contenuto del sito è protetto contro duplicazioni, traduzioni, inserimento o trasformazione dello stesso in altri media, incluso l’inserimento o la trasformazione con mezzi elettronici. La riproduzione e lo sfruttamento economico di tutto o di parte del contenuto di questo sito sono consentite solo a seguito del consenso scritto dell’avente diritto. Sia il contenuto che la struttura del sito sono protetti dal diritto d’autore. In particolare, la duplicazione di informazioni o dati, l’uso dei testi o di parte di essi o delle immagini contenute nel sito (eccetto per le foto ad uso stampa) è consentita solo previo consenso scritto dell’avente diritto. Anche le illustrazioni, a norma dell’art. 1 della legge 633/1941 – e successive modifiche e integrazioni – sono protette dal diritto d’autore. Il diritto di pubblicazione e riproduzione di questi disegni è di titolarità dell’avente diritto. Il diritto d’autore sui disegni rimane in vigore anche per i disegni automaticamente o manualmente aggiunti a un archivio. Nulla di quanto contenuto in questo sito vale come concessione a terzi dei diritti di proprietà industriale ed intellettuale indicati in questa sezione. Ci riserviamo tutti i diritti di proprietà intellettuale del sito web.

Marchi ed immagini riferibili a soggetti terzi utilizzati in questo sito non appartengono a AlNao.it e sono da ritenersi di proprietà esclusiva dei rispettivi titolari. Le denominazioni dei prodotti pubblicati su questo sito web o delle società menzionate, anche qualora non siano indicate con il simbolo identificativo della registrazione del marchio sono marchi di titolarità di terzi e sono protetti dalla legge sui marchi (D.lgs. 30/2005 e successive modifiche e integrazioni) e dalle norme in tema di concorrenza sleale. Qualsiasi riproduzione degli stessi è da ritenersi vietata ai sensi di legge. In particolare è espressamente vietato qualsiasi uso di questi marchi senza il preventivo consenso scritto del relativo titolare ed, in particolare, è vietato utilizzarli in modo da creare confusione tra i consumatori in merito all'origine dei prodotti o per finalità di sponsorizzazione, nonché in qualsiasi modo tale da svilire e discreditare il titolare del marchio. Tutti i diritti che non sono espressamente concessi sono riservati al titolare del marchio.

In aggiunta a quanto indicato, AlNao.it non potrà essere ritenuto in alcun caso responsabile di alcun danno derivante dall'utilizzo o dall'impossibilità di utilizzare il sito web, i contenuti, le informazioni o connessi alla qualità degli stessi.

MENU