Créer une application single-page en Angular 2 Partie 1

L’application Single-page (SPA) intéresse beaucoup l’industrie logicielle car c’est un levier pour améliorer les performances des applications sur les navigateurs et les smartphones. Depuis plusieurs années, l’intérêt des développeurs pour Angular, framework SPA open source, a dépassé les autres frameworks web (React, Backbone, Meteor, etc.). Pour s’en convaincre, il suffit de regarder le nombre de questions sur chaque frameworks sur Stackoverflow :

Angular 2 est disponible depuis septembre 2016. Il ne s’agit pas d’une simple mise à jour dans la version 1.x mais d’un changement complet du framework. Il est fait pour être plus robustesse, offrir une meilleure montée en charge et une multiplateforme moderne pour les applications.

P.S. : nous ne parlerons pas ici d’Angular 4.

Dans ce tutoriel, nous allons voir les blocs clés d’Angular et comment développer une applications SPA et la partie sandbox côté serveur. Il est nécessaire d’avoir des connaissances en JavaScript, TypeScript et HTML. Une connaissance proprement dite d’Angular n’est pas nécessaire.

Le code complet de ce projet est disponible ici.

Pourquoi SPA et Angular 2

Un rendu SPA se fait sur une seule page depuis le serveur. Le serveur envoie le moteur d’application au client. Celui-ci contrôle l’ensemble de l’application (traitement, entrée / sortie, chargement des autres pages, etc.). 90-95 % de l’application s’exécute dans le navigateur. Le reste est sur le serveur. Cette approche permet de réduire la dépendance avec le serveur. Cette approche n’a pas de problème de monter en charge si le nombre d’utilisateurs explose. La charge serveur réduite est aussi une source potentielle de réduction des coûts. Et en utilisant Angular, vous pouvez consommer des microservices dans votre SPA.

Les concepts d’Angular

Les concepts clés d’Angular sont : les modules, les composants, les services, les routes. Une application Angular est modulaire. Toute application Angular est un module. Le module root est nommé AppModule. Il peut être l’unique module dans une petite application, mais vous avez aussi en avoir bien plus. Au développeur de décider comment il veut utiliser les modules. Typiquement, vous pouvez faire un module par fonction.

Le composant contrôle ce que l’on appelle la vue (view). Vous définissez le composant logique de l’application. La classe interagit avec la vue à travers une API. Un composant contient une classe, un template et des metadonnées.

Le service fournit les valeurs, la fonction, la fonctionnalité dont l’application a besoin. Les composants sont des gros consommations de services. Et le service consomme des microservices.

Enfin, la notion « routes » est la navigation d’une vue vers une prochaine vue. C’est l’équivalent du mécanisme gérant les menus et sous-menus.

De quoi avons-nous besoin ?

Pour réaliser notre exemple, nous avons besoin de Node.JS et d’Angular CLI. Les deux doivent être installés sur votre PC de développement.

Installation de Node.JS :
Télécharger Node.JS sur votre ordinateur et choisisser les options par défaut pour terminer l’installation.

Exécuter mode - v sur votre shell pour vérifier le numéro de version. Dans notre cas : v6.9.1.

Le gestionnaire de paquet Node (NPM) est installé automatiquement avec Node. Tapez nom -v pour voir la version. NPM est utilisé en arrière-plan quand vous installez un package provenant du référentiel public. La commande dont il faut se souvenir est npm install, elle chargera et installera les packages listés dans le fichier package.json de votre projet Angular.

Installation de Angular CLI :

Exécuter npm install -g angular-cli@1.0.0-beta.21. Cette version est utilisée par notre application d’exemple. L’installation prendra une dizaine de minutes.

Une fois terminée, tapez ng -v pour vérifier les versions :

angular-cli: 1.0.0-beta.21
node: 6.9.1
os: win32 x64

Pour accéder à l’aide pour connaître les syntaxes de ng, tapez ng help.

Le fichier package.json
Ce fichier, le fichier de métadonnées d’une application Angular, contient les détails et les dépendances de votre application. Ce fichier est l’un des plus importants, surtout quand vous déployez l’application sur un autre ordinateur ou quand vous installez des mises à jour. Ce fichier vérifie que les bonnes versions des packages soient bien installées.
 
Nous n’allons pas nous focaliser sur ce fichier durant ce tutoriel. Mais quand vous déployez des applications qui seront en production, vous devrez être vigilant.
 
Exemple d’un fichier package.json avec les versions des packages :

1

2

3

4

5

6

7

8

9

10

11

12

13

{ "dependencies" :

  { "foo" : "1.0.0 - 2.9999.9999"

  , "bar" : ">=1.0.2 <2.1.2"

  , "baz" : ">1.0.2 <=2.3.4"

  , "boo" : "2.0.1"

  , "qux" : "<1.0.0 || >=2.3.1 <2.4.5 || >=2.5.2 <3.0.0"

  , "til" : "^1.2"

  , "elf" : "~1.2.3"

  , "two" : "2.x"

  , "thr" : "3.3.x"

  , "lat" : "latest"

  }

}

La commande npm install interprète les lignes et les indications données pour les versions :

version : il s’agit de cette version et pas d’une autre

>version : version supérieure à celle indiquée

-version : grosso modo cette version ou équivalent

^version : compatible avec la version

1.2.x : pas une version 1.3.x

* : toute version

(string vide) : même chose que *

version1 - version2 : même chose que >=version1 <=version2

Pour en savoir tapez : npm help

Aperçu de notre projet

Notre projet d’exemple consiste en une application Angular out-of-a-box, avec une application personnalisée développée au-dessus. Quand nous aurons terminé, l’application Angular sera en réalisé, trois petites applications avec des fonctions utilisant trois web services : Weather form Yahoo!, Currency exchange et movie détails.

Toute la logique s’exécutera sur le navigateur. Le serveur sera là pour envoyer les nouvelles données. En réalisé, nous allons éteindre le process serveur peu utilisé dans une application SPA.

Voici la topologie de notre application :

Nous utiliserons Angulaire CLI pour créer notre projet. Par défaut, il inclut AppModule et AppComponent. Nous aurons besoin de 4 composants : menu, weather, movie et currency.

Nous créerons les routes pour la navigation menu et nous injecterons les services weather, movie, currency :

  •                  Data coming from the HTTP that consumes microservices
  •                  Resource sharing across components while the services are used

Créer l’application de base et le module

Ouvrez votre shell et allez au répertoire du projet.

Créer un projet Angular

Pour créer un projet, il suffit de taper :

ng new dw_ng2_app --skip-git

Après l’installation des packages et de toutes les éléments du projet, listez l’ensemble du répertoire /dw_ng2_app, la structure sera la suivante :

|— e2e

|— node_modules

|— src

angular-cli.json

karma.conf.js

package.json

protractor.conf.js

README.md

tslint.json

Le répertoire ../dw_ng2_app/src contient :

|— app

|— assets

|— environments

favicon.ico

index.html

main.ts

polyfills.ts

styles.css

test.ts

tsconfig.json

typings.d.ts

Enfin, le répetoire ../dw_ng2_app/src/app, qui n’est pas le répertoire root module contient :

app.component.css

app.component.html

app.component.spec.ts

app.component.ts

app.module.ts

index.ts

Exécuter l’application Angular en out-of-the-box
Changer le répertoire du projet et exécuter ng serve pour démarrer l’application Angular en out-of-the-box. Par défaut, les process démarrent sur le port 4200. Si le port est différent, les process démarrent sur ces ports. Vous pouvez forcer le port par défaut avec ng serve —port 4200.
Ouvrez votre navigateur et tapez http://localhost:4200/. Si tout se déroule bien, l’application apparait.

Si vous faites des changements dans le code de l’application, Angular voit qu’il y a des changements et redémarrera automatiquement l’application.

Editez le fichier app.components.ts et changez le titre. Vous verrez le changement sur le navigateur.

Comment lier un module à un composant ?

Dans le listing 1, la ligne 20 montre la déclaration du module AppModule :

Listing 1. app.module.ts

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

import { BrowserModule } from '@angular/platform-browser';

import { NgModule } from '@angular/core';

import { FormsModule } from '@angular/forms';

import { HttpModule } from '@angular/http';

 

import { AppComponent } from './app.component';

 

@NgModule({

  declarations: [

    AppComponent

  ],

  imports: [

    BrowserModule,

    FormsModule,

    HttpModule

  ],

  providers: [],

  bootstrap: [AppComponent]

})

export class AppModule { }

Le module contient un seul composant (component) : AppComponent (ligne 10). La ligne 18 indique que le premier composant qui démarrera avec le process bootstrapping est AppComponent. 

A l’intérieur d’un composant

La listing 2 montre à quoi ressemble que le composant de l’application principale dans le fichier app.component.ts :

Listing 2. app.component.ts

1

2

3

4

5

6

7

8

9

10

import { Component } from '@angular/core';

 

@Component({

  selector: 'app-root',

  templateUrl: './app.component.html',

  styleUrls: ['./app.component.css']

})

export class AppComponent {

  title = 'My Angular 2 app works!';

}

Et ici ce à quoi votre application ressemble dans le fichier app.component.html :

1

2

3

<h1>

  {{title}}

</h1>

Les métadonnées
Les métadonnées disent à Angular comme traiter une classe. Concrètement, AppComponent n’est pas un composant comme l’attend Angular en attachant des métadonnées à la classe. Vous attachez les metadonnées en utilisant @Component, qui identifie la classe comme un composant. @Component prend un objet de configuration avec l’information nécessaire à Angular pour créer et exposer le composant et sa vue.
Le listing 2 utilise trois options pour rendre disponibles les options de configuration @Component :

▪                   selector: le sélection CSS dit à Angular de créer et d’insérer une instance de ce composant et où trouver le tag selector dans le fichier HTML.

▪                   templateUrl: composant fichier HTML

▪                   styleUrls: composant de style en cascade comme un fichier CSS.

Localisation du temple à l’intérieur du composant

Un template est une forme de HTML. Il va dire à Angular comment rendre le composant. A la ligne 5 du listing 2, templateUrl indique le nom de la vue app.component.html.

Data binding dans le composant

Le Data binding dit à Angular comment rendre le composant. Dans le fichier app.component.ts, la valeur title est un ensemble dans la classe et il est utilisé dans le fichier app.component.html. Data binding peut être unidirectionnel ou bidirectionnel. Le mapping est unidirectionnel si vous utilisez le double {{ }}. La valeur passe de la classe au fichier HTML.

Créer un composant personnalisé et les routes

Notre application est dores et déjà prête à fonctionner. Notre application de base a un module, un composant, une classe, un template, des métadonnées et du databinding, mais il nous manque encore quelques éléments :

- plusieurs composants (notion de multiple composant)

- le routing

- les services

- consommation de microservices.

Créer des composants personnalisés

Arrêtez le process Angular en utilisant la combinaison Ctrl-C. Attention : soyez bien dans le répertoire du projet dw_ng2_app. Puis tapez les commandes suivantes :

  • ng g c Menu -is --spec false --flat:  crée le composant menu dans le module AppModule et dans le même dossier.
  • ng g c Weather -is --spec false:  crée le composant Weather dans AppModule, dans le sous-dossier weather.
  • ng g c Currency -is --spec false: crée le composant Currency dans le sous-dossier currency
  • ng g c Movie -is --spec false:  crée le composant Movie dans AppModule et dans le sous-dossier movie.

Maintenant que nos composants sont créés, vous pouvez voir comment AppModule fait le lien avec eux. Le listing 3, ligne 28 contient les déclarations du module AppModule. Ce module contient 5 composants, incluant le composant root, voir les lignes 14 à 18.

Listing 3. app.module.ts

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

import { BrowserModule } from '@angular/platform-browser';

import { NgModule } from '@angular/core';

import { FormsModule } from '@angular/forms';

import { HttpModule } from '@angular/http';

 

import { AppComponent } from './app.component';

import { MenuComponent } from './menu.component';

import { WeatherComponent } from './weather/weather.component';

import { CurrencyComponent } from './currency/currency.component';

import { MovieComponent } from './movie/movie.component';

 

@NgModule({

  declarations: [

    AppComponent,

    MenuComponent,

    WeatherComponent,

    CurrencyComponent,

    MovieComponent

  ],

  imports: [

    BrowserModule,

    FormsModule,

    HttpModule

  ],

  providers: [],

  bootstrap: [AppComponent]

})

export

Créer les routes

Commande de création de route

Je fournis ici les instructions de création de route manuelle

Comme indiqué, une commande CLI pour créer les routes est en développement. Vous pouvez vérifier sur le site CLI pour voir sa disponibilité.

Pour la navigation à travers les composants, vous devez créer des routes. Modifiez le menu.component.html avec les listing 4.

Listing 4. menu.component.html

1

2

3

4

5

6

7

8

9

<div class="row">

   <div class="col-xs-12">

    <ul class="nav nav-pills">

     <li routerLinkActive="active"> <a [routerLink]="['/weather']" >Weather</a></li>

     <li routerLinkActive="active"> <a [routerLink]="['/movie']" >Movie Details</a></li>

     <li routerLinkActive="active"> <a [routerLink]="['/currency']" >Currency Rates</a></li>

    </ul>

  </div>

 </div>

Le listing 4 montre le mapping entre l’interface et le chemin URL. Par exemple, quand un utilisateur clique sur “détail d’un film”, Angular sait qu’il a besoin d’exécuter le chemin http///localhost:4200/movie.

L’étape suivante est de mapper les chemins aux composants. Dans le même répertoire que le module root, créez un fichier de configuration ayant pour nom app.routing.ts. Utilisez le code du listing 5.

Listing 5. app.routing.ts

1

2

3

4

5

6

7

8

9

10

11

12

import { Routes, RouterModule } from '@angular/router';

import { CurrencyComponent } from "./currency/currency.component";

import { WeatherComponent } from "./weather/weather.component";

import { MovieComponent } from "./movie/movie.component";

const MAINMENU_ROUTES: Routes = [

    //full : makes sure the path is absolute path

    { path: '', redirectTo: '/weather', pathMatch: 'full' },

    { path: 'weather', component: WeatherComponent },

    { path: 'movie', component: MovieComponent },

    { path: 'currency', component: CurrencyComponent }

];

export const CONST_ROUTING = RouterModule.forRoot(MAINMENU_ROUTES);

Si votre chemin relatif est movie, vous devez indiquer à Angular d’appeler MovieComponent. Le chemin relatif va mapper l’url  http://localhost:4200/movie.

Maintenant, vous devez lier cette vue au composant parent. Réécrire le code du fichier app.component.html avec le code suivant ;

1

2

3

4

5

<div class="container">

 <app-menu></app-menu>

 <hr>

 <router-outlet></router-outlet>

</div>

Le sélectionneur <app-menu></app-menu> est dans le menu. Le sélecteur <router-outlet></router-outlet> est réservé au composant courant. Selon le path URL, la valeur peut être multiple pour les trois composants. Le module doit être notifié pour la route.

Ajoutez deux items dans le app.module.ts comme montré aux lignes 11 et 25 dans le listing 6.

Listing 6. app.module.ts

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

import { BrowserModule } from '@angular/platform-browser';

import { NgModule } from '@angular/core';

import { FormsModule } from '@angular/forms';

import { HttpModule } from '@angular/http';

 

import { AppComponent } from './app.component';

import { MenuComponent } from './menu.component';

import { WeatherComponent } from './weather/weather.component';

import { CurrencyComponent } from './currency/currency.component';

import { MovieComponent } from './movie/movie.component';

import { CONST_ROUTING } from './app.routing';

 

@NgModule({

  declarations: [

    AppComponent,

    MenuComponent,

    WeatherComponent,

    CurrencyComponent,

    MovieComponent

  ],

  imports: [

    BrowserModule,

    FormsModule,

    HttpModule,

    CONST_ROUTING

  ],

  providers: [],

  bootstrap: [AppComponent]

})

export class AppModule { }

Maintenant, si vous exécutez et cliquer sur Weather, l’application affichera weather works.

Même chose si vous cliquez sur Movie Details ou Currency Rates. 

Voilà, vous avez modifié avec succès l’application Angular en incluant des composants et le routing. Maintenant, vous êtes prêt pour les dernières étapes : créer et configurer un service et consommer des microservices.

Fin de la 1ere partie.

Lire la 2eme partie