Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Creare un Servizio in Angular 2

Creare un nuovo servizio sfruttando Angular CLI e rendere il servizio disponibile (provided) all'applicazione.
Creare un nuovo servizio sfruttando Angular CLI e rendere il servizio disponibile (provided) all'applicazione.
Link copiato negli appunti

Oltre a poter utilizzare servizi predefiniti come FormBuilder, che abbiamo già visto, e Http, che vedremo più avanti, Angular 2 ci consente di creare un servizio specifico.

Supponiamo ad esempio di voler separare la gestione della lista degli articoli della nostra applicazione dalla sua visualizzazione. Nella nostra attuale implementazione avevamo assegnato tale compito al componente di root dell'applicazione, AppComponent:

import { Component } from '@angular/core';
import { Articolo } from './articolo'; 
@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.css']
})
export class AppComponent {
  title = 'Articoli Tecnici';
  elencoArticoli: Articolo[]; 
  constructor() {
    this.elencoArticoli = [];
  } 
  addArticolo(articolo) {
    this.elencoArticoli.push(articolo)
  }
}

Creiamo un servizio che si occupi di fornire la lista iniziale degli articoli disponibili e di consentire l'aggiunta di un articolo alla lista.

Il procedimento di creazione del servizio è abbastanza semplice. Sfruttando Angular CLI possiamo digitare il seguente comando per creare un template del nostro servizio:

ng generate service Articoli

Questo comando genera due file:

File Descrizione
articoli.service.ts contiene il codice di partenza del nostro servizio
articoli.service.spec.ts contiene il codice di base per gli unit test del servizio

Oltre ad informarci di aver creato questi file, il comando ng generate ci avvisa di aver creato i file necessari per l'implementazione del servizio, ma che il servizio non è ancora a disposizione (not provided) dell'applicazione.

Torneremo tra un attimo su questo concetto, diamo prima un'occhiata al codice generato nel file articoli.service.ts:

import { Injectable } from '@angular/core'; 
@Injectable()
export class ArticoliService { 
  constructor() { }
}

È stata creata la classe ArticoliService decorata con l'attributo @Injectable(). Questo attributo ha lo scopo di generare i metadati relativi al servizio necessari per poter effettuare una corretta dependency injection da parte del framework.

Integriamo quindi il codice generato da Angular CLI implementando il recupero dell'elenco iniziale degli articoli e l'aggiunta di un nuovo articolo all'elenco:

import { Injectable } from '@angular/core';
import { Articolo } from './articolo'; 
@Injectable()
export class ArticoliService {
  private elencoArticoli: Articolo[]; 
  constructor() {
    this.elencoArticoli = [{
      titolo: "Creare componenti Angular 2",
      autore: "Mario Rossi",
      testo: "Creare componenti con Angular 2 è molto semplice.",
      numApprezzamenti: 0
    },
    {
      titolo: "Creare servizi Angular 2",
      autore: "Roberto Bianchi",
      testo: "Anche creare servizi con Angular 2 è molto semplice.",
      numApprezzamenti: 0
    }];
  } 
  getArticoli(): Articolo[] {
    return this.elencoArticoli;
  } 
  addArticolo(articolo) {
    this.elencoArticoli.push(articolo)
  }
}

Abbiamo definito una proprietà privata elencoArticoli destinata a mantenere l'elenco di articoli corrente. Gli articoli iniziali sono definiti nel costruttore della classe, mentre i metodi getArticoli() e addArticolo() si occupano rispettivamente di restituire l'elenco degli articoli e di aggiungerne uno nuovo.

Rendere disponibile un servizio

La creazione del nostro servizio ArticoliService non lo rende immediatamente disponibile ai componenti della nostra applicazione. Come ci avvisava Angular CLI in fase di generazione, il servizio è stato creato ma non è messo a disposizione e quindi non è direttamente utilizzabile dai componenti o dagli altri servizi della nostra applicazione. Per renderlo disponibile dobbiamo dichiararlo come provider del componente che lo utilizzerà.

Vediamo come si trasforma root component della nostra applicazione che utilizza il servizio ArticoliService per gestire gli articoli da mostrare all'utente:

import { Component} from '@angular/core';
import { Articolo } from './articolo';
import { ArticoliService } from './articoli.service' 
@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.css'] ,
  providers: [ArticoliService]
})
export class AppComponent {
  title = 'Articoli Tecnici';
  elencoArticoli; 
  constructor(private articoliService: ArticoliService) {
    this.elencoArticoli = articoliService.getArticoli();
  } 
  addArticolo(articolo) {
    this.articoliService.addArticolo(articolo);
  }
}

Evidenziamo in particolare l'importazione del nostro servizio e la sua inclusione nell'array dei provider all'interno della dichiarazione del decoratore @Component. L'array providers specifica ad Angular come creare un'istanza del servizio quando questo viene iniettato nel costruttore del componente e normalmente coincide con la classe del servizio stesso.

Il costruttore di AppComponent prevede il parametro articoloService, dichiarato come proprietà privata in modo che sia disponibile per tutti i metodi della classe. All'interno del costruttore viene inizializzato l'elenco degli articoli sfruttando il metodo getArticoli() del servizio, mentre il metodo addArticolo() del componente viene mappato sull'omonimo metodo del servizio.

Questo refactoring non cambierà il funzionamento dell'applicazione ma determina una separazione dei compiti tra il componente, che deve mostrare i dati all'utente ed interagire con esso, ed il servizio, che deve occuparsi di recuperare e gestire il modello dei dati.

La cosa interessante è che configurando il servizio ArticoliService nel componente, esso sarà disponibile non solo in questo componente ma in tutti i componenti figli. cioè, l'istanza del servizio creata dal sistema di dependency injection sarà a disposizione per tutta la gerarchia di componenti discendenti dal componente in cui la dipendenza è stata iniettata.

Questo meccanismo di dependency injection gerarchica ci consente di creare istanze di un servizio solo quando questo è necessario, cioè soltanto quando un componente è effettivamente utilizzato e non a livello globale. Ma se abbiamo la necessità di rendere globalmente disponibile un servizio a tutta l'applicazione non dobbiamo far altro che registrarlo nel modulo principale dell'applicazione stessa, come mostrato dal seguente codice:

import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
...
import { ArticoliService } from './articoli.service'; 
@NgModule({
  imports: [
	...
  ],
  declarations: [
	AppComponent,
	...
  ],
  providers: [
	 ArticoliService
  ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }

In questo modo tutti i componenti dell'applicazione potranno utilizzare il servizio senza bisogno di una sua esplicita registrazione come provider.

Ti consigliamo anche