Dans cet article, on va s’intéresser à la création de la page d’accueil. Suivez le guide!

Introduction

Dans le premier article, on a vu comment créer un projet Angular. Ici, on va voir comment réaliser une page d’accueil qui enchaînera vers la page de connexion (dans l’épisode 3). A noter que je ne vais pas reprendre le projet d’exemple utilisé dans le premier article. J’ai décidé de vous faire suivre mon nouveau projet afin de traiter des cas réels, ça changera des tutoriels qu’on trouve partout.

Structure d’une page Angular

Avant de foncer tête baissée dans le code, il faut d’abord s’intéresser à la structure proposée par Angular. Si on regarde la page par défaut proposée lors de la création du projet, on trouve quatre fichiers:

  1. app.component.html: contenu HTML de la page
  2. app.component.scss: contient les règles CSS pour la page
  3. app.component.spec.ts: contient les tests unitaires qui seront exécutés lors la compilation
  4. app.component.ts: définit le code Javascript de la page et faire le lien avec les trois autres fichiers

La structure proposée est saine et repose sur plusieurs bonnes pratiques (séparation des responsabilités, tests unitaires), ce qui facilite le développement en équipe.

Création de la page d’accueil

Pour créer une page, il faut ajouter un component avec la commande suivante: ng generate page-home

Cette commande va créer le dossier app/page-home et les fameux quatre fichiers évoqués tantôt.

A ce stade, il faut maintenant s’intéresser au fichier app/app.module.ts. En effet, c’est lui qui contient la liste des components et qui indique celui à charger par défaut.

Par défaut, le contenu du fichier app/app.module.ts est le suivant:

    
 1import { NgModule } from '@angular/core';
 2import { BrowserModule } from '@angular/platform-browser';
 3
 4import { AppRoutingModule } from './app-routing.module';
 5import { AppComponent } from './app.component';
 6import { PageHomeComponent } from './page-home/page-home.component';
 7
 8@NgModule({
 9  declarations: [
10    AppComponent,
11    PageHomeComponent
12  ],
13  imports: [
14    BrowserModule,
15    AppRoutingModule
16  ],
17  providers: [],
18  bootstrap: [AppComponent]
19})
20export class AppModule { }

Pour que la page d’accueil soit celle affichée par défaut, il suffit de remplacer la ligne bootstrap: [AppComponent] par bootstrap: [PageHomeComponent]

Ce n’est pas suffisant, il faut encore lier le component au tag principal. Pour cela, il faut modifier le fichier app/page-home.component.ts. Son contenu initial est le suivant:

    
 1import { Component, OnInit } from '@angular/core';
 2
 3@Component({
 4  selector: 'app-page.home',
 5  templateUrl: './page-home.component.html',
 6  styleUrls: ['./page-home.component.scss']
 7})
 8export class PageHomeComponent implements OnInit {
 9
10  constructor() { }
11
12  ngOnInit(): void {
13  }
14}

Il faut remplacer la ligne selector: 'app-page.home' par selector: 'app-root'

Intermède graphique

A ce stade, on n’a ni CSS ni web composants, autant dire que c’est la dèche et qu’on ne va pas avancer rapidement, tout en réinventant la roue à chaque élément. On va donc ajouter deux choses, à savoir le kit Angular Material UI et le framework Bulma (plus léger et tout aussi efficace que Bootstrap -IMHO-).

Ajout de Angular Material UI

Le kit Angular Material UI fournit un certain nombre de web composants (calendrier, toolbar, icônes, etc). Pour l’ajouter, il suffit d’exécuter la commande

    
1ng add @angular/material

La réponse est la suivante (j’ai mis en bleu les réponses aux quelques questions posées durant l’installation):

    
 1 Using package manager: npm
 2 Found compatible package version: @angular/material@12.2.10.
 3 Package information loaded.
 4 
 5The package @angular/material@12.2.10 will be installed and executed.
 6Would you like to proceed? Yes
 7 Package successfully installed.
 8? Choose a prebuilt theme name, or "custom" for a custom theme: Custom
 9? Set up global Angular Material typography styles? Yes
10? Set up browser animations for Angular Material? Yes
11UPDATE package.json (1135 bytes)
12 Packages installed successfully.
13UPDATE src/app/app.module.ts (599 bytes)
14UPDATE src/styles.scss (1597 bytes)
15UPDATE src/index.html (575 bytes)

On constate qu’un fichier SCCS a été ajouté et contient un minimum de code à personnaliser.

Ajout de Bulma

Bulma est un framework CSS, qui propose de nombreuses classes utilitaires ainsi qu’un système de grille. C’est un très bonne alternative à Bootstrap. Pour l’installer, il faut utiliser la commande suivante:

    
1npm install --save bulma

Puis il faut ajouter la ligne @import 'bulma/css/bulma.css'; dans le fichier style.scss (juste après _@include mat.core();`).

Fin de l’intermède graphique.

Ajout du contenu à la page

Dans le fichier app/page-home/page-home-component.html, on va ajouter le code HTML suivant:

    
 1<div class="dark-wrapper">
 2    <section class="hero is-fullheight is-transparent">
 3        <div class="hero-head">
 4        </div>
 5        <div class="hero-body">
 6            <div class="container">
 7                <div class="columns is-vcentered">
 8                    <div class="column is-5 landing-caption">
 9                        <h1 class="title is-1 is-light is-semibold is-spaced main-title">HomeGED</h1>
10                        <h2 class="subtitle is-6 is-light is-thin">Organiser facilement vos documents</h2>
11                        <p>
12                            <a href="#" class="button is-primary is-fat is-bold is-rounded" tabindex="01">Connexion&nbsp;<i class="fas fa-sign-in-alt" aria-hidden="true"></i></a>
13                            <a href="#" data-bind="click: gotoRegister" class="button is-fat is-bold is-rounded" tabindex="02">Inscription&nbsp;<i class="fas fa-user" aria-hidden="true"></i></a>
14                        </p>
15                    </div>
16                    <div class="column is-7">
17                        <figure class="image">
18                            <img src="assets/page-home/home.jpg" alt="Librairie" class="ged-home-illu">
19                        </figure>
20                    </div>
21                </div>
22            </div>
23        </div>
24        <div class="hero-foot">
25            <div class="container">
26                <div class="tabs is-centered"></div>
27            </div>
28        </div>
29    </section>
30</div>

On aura pris soin au préalable de copier la photo suivante (Auteur: Giammarco) dans le dossier assets/page-home, sous le nom home.jpg.

Du côté de la CSS, il faut ajouter la classe ged-home-illu dans le fichier style.scss:

    
1.ged-home-illu {
2    border: 1px solid #222222;
3    border-radius: 6px;
4}

Ensuite on compile avec la commande ng build puis on lance le rendu avec ng serve et on obtient cette page:

Angular: première page

Angular: première page

(Pour le fun: à ce stade, le projet occupe 628Mo…)

Les plus observateurs auront remarqué un bug: j’ai utilisé des icônes “FontAwesome” sur les deux boutons mais je n’ai pas chargé les CSS nécessaires. C’est normal et je vais expliquer pourquoi.

Utiliser de beaux pictogrammes

Pour ajouter Font Awesome, il faut exécuter la commande suivante:

    
1ng add @fortawesome/angular-fontawesome@0.9.0

Il faudra choisir quels lots d’icônes installer (j’ai choisi les trois “free”: Free Solid, Free Regular et Free Brands). La réponse de la commande est celle-ci:

    
 1 Using package manager: npm
 2 Package information loaded.
 3 
 4The package @fortawesome/angular-fontawesome@0.9.0 will be installed and executed.
 5Would you like to proceed? Yes
 6 Package successfully installed.
 7? Choose Font Awesome icon packages you would like to use: Free Solid Icons, Free Regular Icons, Free Brands Icons
 8    Formatting was skipped because tslint is not installed.
 9UPDATE package.json (1420 bytes)
10UPDATE src/app/app.module.ts (692 bytes)
11 Packages installed successfully.

Ensuite il faut éditer le fichier app/app.module.ts pour inclure le package FontAwesome. On obtient le fichier suivant:

    
 1import { NgModule } from '@angular/core';
 2import { BrowserModule } from '@angular/platform-browser';
 3
 4import { AppRoutingModule } from './app-routing.module';
 5import { AppComponent } from './app.component';
 6import { PageHomeComponent } from './page-home/page-home.component';
 7import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
 8import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
 9
10@NgModule({
11  declarations: [
12    AppComponent,
13    PageHomeComponent
14  ],
15  imports: [
16    BrowserModule,
17    AppRoutingModule,
18    BrowserAnimationsModule,
19    FontAwesomeModule
20  ],
21  providers: [],
22  bootstrap: [PageHomeComponent]
23})
24export class AppModule { }

Maintenant il faut ajouter les icônes dans notre component. D’abord on modifie le script app/page-home/page-home-component.ts en important les icônes nécessaires:

    
1import { faSignInAlt } from '@fortawesome/free-solid-svg-icons';import { faUser } from '@fortawesome/free-solid-svg-icons';

Puis, dans le même fichier, on exporte ces deux icônes:

    
1export class PageHomeComponent implements OnInit {
2  faSignInAlt = faSignInAlt;
3  faUser = faUser;
4}

Au final, le script complet est le suivant:

    
 1import { Component, OnInit } from '@angular/core';
 2import { faSignInAlt } from '@fortawesome/free-solid-svg-icons';
 3import { faUser } from '@fortawesome/free-solid-svg-icons';
 4
 5@Component({
 6  selector: 'app-root',
 7  templateUrl: './page-home.component.html',
 8  styleUrls: ['./page-home.component.scss']
 9})
10export class PageHomeComponent implements OnInit {
11
12  constructor() { }
13
14  ngOnInit(): void {
15  }
16
17  faSignInAlt = faSignInAlt;
18  faUser = faUser;
19}

Maintenant on modifie la page HTML app/page-home/page-home-component.html et on remplace les deux tags <i class="fa... par deux <fa-icon [icon]=.... La page est alors la suivante:

    
 1<div class="dark-wrapper">
 2    <section class="hero is-fullheight is-transparent">
 3        <div class="hero-head"></div>
 4        <div class="hero-body">
 5            <div class="container">
 6                <div class="columns is-vcentered">
 7                    <div class="column is-5 landing-caption">
 8                        <h1 class="title is-1 is-light is-semibold is-spaced main-title">HomeGED</h1>
 9                        <h2 class="subtitle is-6 is-light is-thin">Organiser facilement vos documents</h2>
10                        <p>
11                            <a href="#" class="button is-primary is-fat is-bold is-rounded" tabindex="01">Connexion&nbsp;<fa-icon [icon]="faSignInAlt"></fa-icon></a>
12                            <a href="#" data-bind="click: gotoRegister" class="button is-fat is-bold is-rounded" tabindex="02">Inscription&nbsp;<fa-icon [icon]="faUser"></fa-icon></a>
13                        </p>
14                    </div>
15                    <div class="column is-7">
16                        <figure class="image">
17                            <img src="assets/page-home/home.jpg" alt="Librairie" class="ged-home-illu">
18                        </figure>
19                    </div>
20                </div>
21            </div>
22        </div>
23        <div class="hero-foot">
24            <div class="container">
25                <div class="tabs is-centered"></div>
26            </div>
27        </div>
28    </section>
29</div>

La page est alors transformée ainsi:

Angular: première page avec des icônes

Angular: première page avec des icônes

Alors, si jusque là j’étais plutôt conquis par Angular, je dois dire que le coup d’importer les icônes une par une dans le code JavaScript pour les rendre disponibles dans le HTML comme n’importe quelle variable est plutôt contre-intuitif et franchement lourd à manipuler. Je n’ose pas imaginer l’intégration d’un grand nombre de pictogrammes dans un component du genre menu principal.

Conclusion

La page n’est pas tout à fait terminée puisqu’il manque les liens sur les boutons. Mais honnêtement, après le coup des pictogrammes, j’hésite à continuer à développer avec Angular (Spoiler: et je n’ai pas encore parlé de changer les couleurs par défaut). Il me reste quand même à évaluer l’intégration dans un projet complet avec packaging en format WAR. A suivre donc.