3.3 Angular
3.3.2 AppModule
L’AppModule può essere considerato, per ovvie ragioni, il modulo più im- portante dell’intero progetto ed è situato, come ogni tipico progetto Angular
nella cartella /app. Consta di due file principi: app.module e app-routing.module. Mentre una piccola applicazione potrebbe avere un solo Module, la maggior
parte delle app ha molti più moduli di funzionalità [26] come in questo caso.
1 import{ NgModule }from’@angular/core’;
2 import{ BrowserModule }from’@angular/platform−browser’;
3 import{ HttpClientModule }from’@angular/common/http’;
4 import{ AppComponent }from’./app/app.component’;
5 import{ AppRoutingModule }from’./app−routing.module’;
6 ... 7 @NgModule({ 8 declarations : [ 9 AppComponent, 10 NavbarComponent, 11 SidebarComponent 12 ], 13 imports: [ 14 BrowserModule, 15 AppRoutingModule, 16 HttpClientModule, 17 ... 18 ], 19 bootstrap: [AppComponent], 20 providers: [] 21 })
22 exportclass AppModule { }
Essendo Angular 7 implementato in Typescript, segue la sua sintassi. Nella parte iniziale del file, sono importate tutte le dipendenze. Quelle essenziali sono le seguenti:
• NgModule: Decorator22 che contrassegna una classe come modulo e
fornisce i metadati di configurazione racchiusi nel JSON @NgModule; 22I Decorator rappresentano un pattern di progettazione utilizzato in vari linguaggi di programmazione come Javascript o Python. La sua peculiarità riguarda l’aggiunta di un singolo oggetto staticamente o dinamicamente senza che si influisca con il suo comporta- mento su altri oggetti. Tutto ciò per aderire al concetto di Single Responsibility, il quale prevede che ogni componente debba assolvere ad un unica funzione per la quale è stata creata(Bojan Gvozderac 2017).
• BrowserModule: Modulo che permette di esportare l’app sul Brow- ser;
• HttpClientModule: Modulo che predispone l’app alle chiamate Http; Gli altri due import permettono di aggiungere rispettivamente il Component inerente il Modulo e il file di configurazione del Routing.
I metadati di configurazione a cui si è accennato prima, permettono di settare tutte le componenti.
• declarations: racchiude tutte le direttive, e componenti che appar- tengono a seguente modulo e che sono dichiarate per essere usate ai fini implementativi della logica che espone;
• imports: contiene tutte le classi che sono necessarie per conferire un modello di comportamento al modulo. Ad esempio, senza l’imports de modulo Http non è possibile comunicare con il server;
• exports: permette di esportare le funzionalità che questo modulo implementa e definisce all’esterno, in modo che gli altri moduli pos- sano usufruirne secondo il modello della Dependency Injection,visto poc’anzi.
• bootstrap:ha al suo interno la vista principale del modulo. Dice al motore Angular quale component avviare. In questo caso,è l’AppCom- ponent;
• providers: grazie a questo meta dato, si definisce un modulo come un Service e permette di esportarlo al di fuori, così come viene fatto con il metadato exports per le componenti.
In generale si può asserire come gli import, rendono disponibile al modulo il loro utilizzo, mentre i metadati, definiscono la funzione da usare.
Tra gli import presenti nello script, quello di routing, è molto importante23.
La sua funzione è di switchare tra le varie tab dell’applicazione:
1 import{ NgModule }from’@angular/core’;
2 import{ Routes, RouterModule }from’@angular/router’; 23può anche essere incluso nello stesso file
3 const routes: Routes = [ 4 { 5 path: ’ ’ , 6 children : 7 [ 8 { 9 path: ’ ’ , 10 redirectTo: ’/doors’, 11 pathMatch: ’full ’ 12 }, 13 { 14 path: ’doors’, 15 loadChildren: ’ ./ features/doors/doors.module#DoorsModule’ 16 }, 17 { 18 path: ’ sellout ’ ,
19 loadChildren: ’ ./ features/ sellout / sellout .module#SelloutModule’
20 }, 21 { 22 path: ’country’, 23 loadChildren: ’ ./ features/country/country.module#CountryModule’ 24 }, 25 ... 26 ] 27 } 28 ]; 29 30 @NgModule({
31 imports: [RouterModule.forRoot(routes)], // important: this is forChild and not forRoot
32 exports: [RouterModule]
33 })
34 exportclass AppRoutingModule { }
Come si può vedere, esso sembra un modulo a se stante. Lo si può supporre dall’import NgModule e dai relativi metadati. Tuttavia, è diverso. Ciò che lo contraddistingue, è la presenza del routing con il quale si da la pos- sibilità all’utente di cambiare la view con un click. Per ognuna esiste un percorso. Ad esempio, se si vuole vedere la tab delle Country, si dovrà di- gitare l’indirizzo http://localhost:4200/country o tramite url o tramite la corrispondente tab nella Sidebar, la quale rimanderà allo stesso url. Di default, se nessun percorso è assegnato, viene chiamato il Modulo relativo alle Doors. 1 { 2 path: ’ ’ , 3 redirectTo: ’/doors’, 4 pathMatch: ’full ’ 5 },
Il routing opera sulla Sidebar. La sua collocazione è posta ad un livello gerarchico superiore rispetto gli altri Moduli del progetto, quindi nell’AppModule. I metadati @NgModule inizializzano il router e lo metto-
no in ascolto. L’import configura route in un solo passaggio chiamando RouterModule.forRoot(routes), mentre l’export lo rende accessibile at- traverso l’app, nel caso specifico dal file /app/app/app.component.html. Esso, è come segue:
1 <!−− Define NavBar −−> 2 <app−navbar></app−navbar> 3 4 <!−− Define sidebar −−> 5 <app−sidebar></app−sidebar> 6
7 <divclass="theme−wrapper {{theme$ | async}}">
8 <divclass="main−container">
9 <router−outlet></router−outlet>
10 </div>
11 </div>
Al suo interno, è settato il punto di accesso tra le varie componenti dell’ applicazione del router. Il main-container ha il compito di ospitare il rendering delle diverse tab selezionate attraverso la Sidebar. La dicitura theme-wrapper {{theme$ | async }} asserisce come tutto il container de- ve rispettare i canoni di layout definiti da file css.
Il file che definisce la logica del template html è un file con estensione ts: app.component.ts
1 import{ ChangeDetectorRef, Component, OnInit, OnDestroy }from’@angular/core’;
2 ... 3 4 @Component({ 5 selector : ’app−root’, 6 templateUrl: ’ ./app.component.html’, 7 styleUrls : [ ’ ./app.component.scss’] 8 })
9 exportclass AppComponent implements OnInit, OnDestroy {
10 // variable
11 private _mobileQueryListener: () => void;
12 mobileQuery: MediaQueryList;
13 theme$: Observable<string>;
14 15
16 constructor(changeDetectorRef: ChangeDetectorRef, media: MediaMatcher, private store: Store<State>) {
17 this .mobileQuery = media.matchMedia(’(max−width: 600px)’);
18 this ._mobileQueryListener = () => changeDetectorRef.detectChanges();
19 this .mobileQuery.addListener(this._mobileQueryListener); 20 } 21 22 ngOnInit() { 23 ... 24 } 25 26 ngOnDestroy(): void { 27 ... 28 } 29 }
Questo file rappresenta il vero fulcro della logica di ogni modulo. Viene decretato come Component per via dell’import dal @angular/core24 del
Decorator "Component" . Con esso, si definisce
• un selettore identificativo dell’url di riferimento, app-root;
• il template di riferimento con @angular/templateUrl, in questo caso rappresentato dal file app.component.html;
• il file di stile che sancisce il layout: styleUrls, il quale fa riferimento a app.component.scss.
Nel costruttore sono importati i servizi necessari alla root del progetto. Avendo come obiettivo quello di definire il comportamento a livello mo- bile, sono importati i ChangeDetectorRef e MediaMatcher.
I metodi ngOnInit() e ngOnDestroy() fanno parte del "Ciclo di Vita" della Component e sono metodi che mettono a disposizione degli eventi ad ogni singolo passaggio dalla sua creazione alla sua distruzione. i più importanti sono:
• ngOnChanges(): chiamato prima di ngOnInit(), ogni volta che cambia una o più proprietà di input associate ai dati;
• ngOnInit(): chiamato una volta, dopo il primo ngOnChanges(). Ini- zializza tutte le variabili che vengono istanziate per la prima vol- ta. Eventuali rilevazioni di cambiamenti, non saranno captati da tale metodo.
• ngOnDestroy(): Quando il cicli di vita della component arriva a compimento, tale metodo conterrà le chiamate necessarie per la pu- lizia di tutte le direttive o qualunque variabile impiegata nella logica implementata.
Eventuali altri metodi riguardanti il ciclo di vita, sono consultabili sulla guida ufficiale [26].
24rappresenta uno dei package principali di Angular. Importa tutte le funzionalità, i servizi di basso livello e le utility necessarie ad Angular.