Servizio external-data, creazione

Servizio external-data, creazione

Fino a questo punto il Component lista-eventi e quello dettaglio-evento gestivano dei dati allocati localmente. Ora vediamo come rendere più congruente il loro funzionamento condividendo gli stessi dati. Il reperimento di dati esterni ai componenti e/o la condivisione di dati fra diversi componenti si implementa coi Service,  iniettandoli nei componenti stessi. Per creare questo nostro primo servizio, che chiameremo ExternalData, daremo da Shell il seguente comando Angular:

ng generate service services\externalData 

 

Nel folder di progetto (nel mio caso C:\tutorial\agenda-eventi\src\app) viene creata una directory services contenente i due file external-data.service.ts e external-data.service.spec.ts. Al solito del file con estensione .spec.ts decidiamo al momento di disinteressarci.

MODIFICA DEL FILE external-data.service.ts


 
import { Injectable } from "@angular/core";

const dati_Lista_Eventi = [
  {
    id: 13,
    name: "Swing Fastival",
    country: " United Kingdom",
    town: " Torquay, Devon ",
    site2: "http://www.swingfastival.co.uk",
    styles: " Balboa, Shag",
    startdate: "2019-11-08",
    stopdate: "2019-11-10"
  },
  {
    id: 14,
    name: "Boulevard Blues",
    country: " Belgium",
    town: " Hasselt",
    site2: "www.boulevardblues.be ",
    styles: " Blues",
    startdate: "2019-11-08",
    stopdate: "2019-11-11"
  },
  {
    id: 124,
    name: "Montpellier Balboa Rendez-Vous",
    country: " France",
    town: " Montpellier",
    site2: "http://www.swingcatcie.com/montpellier-balboa-rendezvous/",
    styles: " Balboa, Shag",
    startdate: "2020-02-14",
    stopdate: "2020-02-16"
  },
  {
    id: 125,
    name: "Holy lollies",
    country: "France",
    town: " Strasbourg",
    site2: "http://www.holylollies.fr",
    styles: " Balboa",
    startdate: "2020-02-14",
    stopdate: "2020-02-16"
  },
  {
    id: 208,
    name: "Black Forest Hop",
    country: " Germany",
    town: " Freiburg",
    site2: "http://www.blackforesthop.com",
    styles: " Lindy Hop",
    startdate: "2020-06-05",
    stopdate: "2020-06-07"
  },
  {
    id: 223,
    name: "JazzOut SwingFest",
    country: " Netherlands",
    town: " Nijmegen",
    site2: "http://www.jazzoutswingfest.com/",
    styles: " Jazz, Lindy Hop",
    startdate: "2020-08-28",
    stopdate: "2020-08-30"
  },
  {
    id: 224,
    name: "Shirt Tail Stompers 10 Year Aniversary Weekend",
    country: " Lithuania",
    town: " Vilnius",
    site2: "https://www.facebook.com/events/2981610321881346/",
    styles: " Balboa, Charleston, Jazz, Lindy Hop, Shag",
    startdate: "2020-08-28",
    stopdate: "2020-08-30"
  },
  {
    id: 225,
    name: "Swinging and Sail",
    country: " Greece",
    town: " Athens - Ithaca",
    site2: "http://www.swingnsail.com",
    styles: " Lindy Hop",
    startdate: "2020-08-28",
    stopdate: "2020-09-05"
  },
  {
    id: 226,
    name: "Madrid in Pulse",
    country: " Spain",
    town: " Madrid",
    site2: "http://www.madridinpulse.es/?lang=en",
    styles: " Balboa",
    startdate: "2020-09-04",
    stopdate: "2020-09-06"
  }
];

@Injectable({
  providedIn: "root"
})
export class ExternalDataService {
  constructor() {}

  getEventi() {
    return dati_Lista_Eventi;
  }

  getEvento(id: number) {
    for (var i in dati_Lista_Eventi) {
      if (dati_Lista_Eventi[i].id == id) {
        return dati_Lista_Eventi[i];
      }
    }
    return null;
  }
}

Questo servizio al momento contiene i soli dati di esempio assegnati alla variabile dati_Lista_Eventi e che vengono resi disponibili attraverso i metodi getEventi e getEvento

MODIFICA DEL FILE lista-eventi.components.ts

… per utilizzare il nuovo servizio e non più dati definiti localmente. Come? Iniettando nel costruttore ExternalDataService e utilizzandone il metodo getEventi in fase di inizializzazione del componente.

import { Component, OnInit } from "@angular/core";
import { ExternalDataService } from "../../services/external-data.service";

@Component({
  selector: "app-lista-eventi",
  templateUrl: "./lista-eventi.component.html",
  styleUrls: ["./lista-eventi.component.css"]
})
export class ListaEventiComponent implements OnInit {
  displayedColumns: string[] = ["evento", "luogo", "balli", "inizio", "fine"];
  datiListaEventi = null;

  constructor(private externalDataServiceExternalDataService) {}

  ngOnInit() {
    this.datiListaEventi = this.externalDataService.getEventi();
  }
}

MODIFICA DEL FILE dettaglio-evento.component.ts

In modo analogo anche questo componente smette di usare i dati cablati con la precedente inizializzazione della variabile singoloEvento per recuperli invece dall’ ExternalDataService con il metodo getEvento. Si noti la semplicità della sintassi per recuperare dal parametro dell’url (ad es. http://localhost:4200/dettaglio-evento/225) l’id, attraverso l’ActivatedRoute.

import { Component, OnInit } from "@angular/core";

import { ActivatedRoute } from "@angular/router";
import { ExternalDataService } from "../../services/external-data.service";

@Component({
  selector: "app-dettaglio-evento",
  templateUrl: "./dettaglio-evento.component.html",
  styleUrls: ["./dettaglio-evento.component.css"]
})
export class DettaglioEventoComponent implements OnInit {
  singoloEvento = null;

  constructor(
    private route: ActivatedRoute,
    private externalDataServiceExternalDataService
  ) {}

  ngOnInit() {
    this.singoloEvento = this.externalDataService.getEvento(
      this.route.snapshot.params["id"]
    );
  }
}

Sia per il componente lista-eventi che per dettaglio-evento è cambiata la parte di controllo, non quella di presentazione. Quindi non sarebbe necessario modificare nessuno dei due file html relativi. Tuttavia ora ci serve introdurre una nuova funzionalità. Vogliamo che cliccando su una riga della lista-eventi, il componente dettaglio-evento si apra proprio su quello, diverso riga per riga.

MODIFICA DEL FILE lista-eventi.component.html

Utilizzando  l’attributo routerLink valorizzato con l’id dell’evento coi dati mostrati alla row-esima riga, riusciamo visualizzare il dettaglio dello specifico evento.

<div class="inner-list">
  <table
    mat-table
    [dataSource]="datiListaEventi"
    class="event-table"
    matSort
    matSortActive="startdate"
    matSortDisableClear
    matSortDirection="asc"
  >
    <ng-container matColumnDef="evento">
      <th mat-header-cell *matHeaderCellDef>Evento</th>
      <td mat-cell *matCellDef="let row">{{ row.name }}</td>
    </ng-container>

    <ng-container matColumnDef="luogo">
      <th mat-header-cell *matHeaderCellDef>Luogo</th>
      <td mat-cell *matCellDef="let row">{{ row.country }} / {{ row.town }}</td>
    </ng-container>

    <ng-container matColumnDef="balli">
      <th mat-header-cell *matHeaderCellDef>Balli</th>
      <td mat-cell *matCellDef="let row">{{ row.styles }}</td>
    </ng-container>

    <ng-container matColumnDef="inizio">
      <th mat-header-cell *matHeaderCellDef>Inizio</th>
      <td mat-cell *matCellDef="let row">{{ row.startdate }}</td>
    </ng-container>

    <ng-container matColumnDef="fine">
      <th mat-header-cell *matHeaderCellDef>Fine</th>
      <td mat-cell *matCellDef="let row">{{ row.stopdate }}</td>
    </ng-container>

    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
    <tr
      mat-row
      *matRowDef="let row; columns: displayedColumns"
      [routerLink]="['/dettaglio-evento/', row.id]"
    ></tr>
  </table>
</div>

Abbiamo finito. Possiamo rilanciare ng serve e verificare che tutto funzioni. In questo articolo abbiamo visto come incapsulare il reperimento dei dati utili alla nostra applicazione in un Servizio appositamente dedicato. In questo modo, il come avvenga il reperimento dei dati è un problema isolato a questo solo modulo. I componenti che utilizzeranno i dati devono potersi disinteressare se i dati sono in una variabile dell’applicazione, in un file, in un DB o su un server remoto. E’ il caso più tipico della necessità di un Servizio Angular.

Le due videate, lista-eventi e dettaglio-evento sono collegate attraverso il click sulle righe della tabella degli eventi. Per farlo abbiamo imparato ad utilizzare l’attributo routerLink in lista-eventi.component.html e il Servizio ActivatedRoute in dettaglio-evento.component.ts.

No Comments

Sorry, the comment form is closed at this time.