Bootstrap avec Angular 18

Mis à jour : 14/06/2024 danny

Bootstrap est le plus connu et le plus utilisé des Frameworks CSS.

Nous allons intégrer Bootstrap version 5.3.3 dans notre Application Web.

Nous utiliserons pour cela le framework javascript Angular version 18.0.2

Bootstrap avec Angular
Bootstrap avec Angular

Si vous n'avez pas le temps de lire ce guide en entier,
téléchargez le maintenant


Ce que nous allons faire

  • Qu'est-ce que Bootstrap ?
    Nous allons parler de bootstrap et de son utilité dans les sites Web.
     
  • Création de notre projet Angular
    Nous utiliserons un projet existant contenant les fonctionnalités essentielles.
    Le projet a été généré avec Angular CLI et utilise le Routing et le Lazy Loading.
     
  • Prototype Bootstrap
    Pourquoi et comment créer un prototype Bootstrap ?
     
  • Version 4 versus Version 5
    Quelle version de bootstrap devriez-vous choisir ?
     
  • Intégration à notre projet angular
    Comment intégrer Bootstrap en utilisant Angular CLI ?
     
  • Effectuer les Tests
    Nous testerons notre application via les tests unitaires et end-to-end intégrés dans Angular.
     
  • Code source
    Pour les plus pressés d'entre vous, le code complet du projet.
    https://github.com/ganatan/angular-react-bootstrap

 


Qu'est-ce que Bootstrap ?

Les pages d'un site web sont écrites en utilisant 3 types de langages informatiques (computer language en anglais)

  • Le langage HTML
    H
    yperText Markup Language (Langage de Balisage HyperText)
    il permet de créer et de représenter le contenu d'une page web et sa structure.
     
  • Le langage CSS
    Cascading Style Sheets (Feuilles de style en cascade)
    il est utilisé pour décrire la présentation d'une page.
     
  • Le langage Javascript
    Il permet de créer des fonctionnalités interactives dans la page.


De nombreux outils permettent de simplifier la vie d'un développeur.
Notamment les Frameworks CSS qui constituent en quelque sorte des boites à outils graphiques.

Les Framework CSS sont extrêmement nombreux, parmi ceux-ci nous pourrions citer

  • Foundation
  • Materialize CSS
  • Bootstrap
  • Pure

Bootstrap est l'un des frameworks CSS les plus connus et les plus utilisés.

Bootstrap est sous licence open source depuis 2011.
Son utilisation est donc gratuite.

Il permet de créer des sites responsive.
C'est à dire qu'il permet d'adapter un site web à toute sorte de périphériques (ordinateur, smartphone ou tablette).

La version actuelle est la version 5.3.2


Création du projet Angular

Pour pouvoir continuer ce tutoriel nous devons bien évidemment disposer de certains éléments

  • Node.js : La plateforme javascript
  • Git : Le logiciel de gestion de versions. 
  • Angular CLI : L'outil fourni par Angular.
  • Visual Studio code : Un éditeur de code.

Vous pouvez consulter le tutoriel suivant qui vous explique en détails comment faire


Nous allons utiliser un projet existant dont les caractéristiques sont

  • Genéré avec Angular CLI
  • Routing
  • Lazy loading

Vous pouvez installer ce projet sur votre poste de travail en utilisant les commandes suivantes.

# Créez un répertoire demo (le nom est ici arbitraire)
mkdir demo

# Allez dans ce répertoire
cd demo

# Récupérez le code source sur votre poste de travail
git clone https://github.com/ganatan/angular-lazy-loading.git

# Allez dans le répertoire qui a été créé
cd angular-lazy-loading
cd angular

# Exécutez l'installation des dépendances (ou librairies)
npm install

# Exécutez le programme
npm run start

# Vérifiez son fonctionnement en lançant dans votre navigateur la commande
http://localhost:4200/

Pourquoi Créer un prototype Bootstrap ?

En simplifiant il y a 3 types de développeur Web

  • Frontend
  • Backend
  • Fullstack

On pourrait rajouter un 4ème métier

  • Web Designer


Toujours en simplifiant, les 3 premiers s'occupent de la partie logique et le quatrième de la partie graphique.

C'est pour cela que nous allons créer tout d'abord un prototype graphique.
Ce prototype servira de base à la phase de conception de votre site web.

Quelques raisons de ce choix.

  • Il est plus difficile et coûteux de faire des changements dans le code plutôt que dans un prototype.
  • Si vous êtes amené à travailler en équipe, il est plus facile de savoir qui fait quoi.
  • Il existe de nombreux outils de prototypage.
  • Il facilite l’évolution et l'amélioration de l’interface.
  • Il est plus rapide et facile de présenter un prototype à un éventuel client.

Donc.

Pour se faire, il n'est pas utile de connaitre Angular.
Seule la connaissance de HTML,CSS et d'un peu de javascript sera nécessaire.


Il sera même possible de sous-traiter à un partenaire Web Designer ou graphiste.

Ce sont certains des éléments de ce prototype que nous intégrerons à notre application Angular.

L'architecture de ce prototype et le choix des noms est bien sûr arbitraire.
Vous pouvez l'adapter à votre convenance.


Rapide résumé du prototypage

La conception d'un site web passera par plusieurs étapes.
L'une d'entre elles est le prototypage.
Le prototypage consiste à créer un exemplaire non définitif de ce que pourra être le produit final.
Il permet de concevoir une Interface Utilisateur ou UI (User Interface)

Il existe 2 étapes de prototypage.

  • Prototypage horizontal
    Créer une maquette statique.
    Dessiner un schéma (wireframe)
    Définir les zones et composants
     
  • Prototypage vertical
    Intégrer les fonctionnalités

Nous allons dans le cadre de ce tutoriel créer simplement une maquette statique.


Comment créer un prototype bootstrap ?

Histoire de comprendre ce que l'on fait, nous n'utiliserons aucun outil de prototypage.
Nous concevrons ce prototype manuellement et à partir de rien (from scratch).

Le répertoire qui contiendra ce prototype sera UI ou User Interface (pour Interface Utilisateur).

Une image va nous permettre d'avoir une vue d'ensemble de notre prototype au sein de notre application Angular.

Prototype Bootstrap

Passons à la pratique.
Nous allons chercher sur le web tous les éléments nécessaires que nous placerons dans l'arborescence de notre projet Angular.

Nous obtiendrons au final l'arborescence suivante.

|-- node_modules/          (contient les librairies node) 
|-- src/          (contient le code source de notre application angular) 
|-- ui/                    ( contient notre prototype bootstrap)
    |-- assets
        |-- bootstrap
            |-- css
            |-- js
        |-- fontawesome
            |-- css
            |-- js
            |-- webfonts
        |-- params
            |-- css
            |-- images
            |-- js
package.json

Version 4 vs Version 5

Bootstrap 4 c'est bien sympa.
Mais la version 5 est sortie le 16 juin 2020.

La dernière version est la version 5.3.3

Il est intéressant de voir que cette version apporte deux modifications majeures.

  • La suppression de Jquery.
    Et par conséquence l'utilisation de Vanilla javascript ( autrement dit du javascript rien que du javascript)
  • L'abandon de la compatibilité avec IE 10 et 11 (Internet Explorer)
    C'était pas trop tôt

Le projet final utilisera la version 5, j'ai testé, ça marche, alors pourquoi pas !

Au diable la prudence.
On aura le temps d'être prudent quand on sera mort.


 


Les éléments du prototype

Donc commençons !

Dans le répertoire ui créez un répertoire assets.
Dans ce répertoire assets créez les 3 répertoires suivants

  • bootstrap
  • fontawesome
  • params

Récupérons maintenant les différents éléments utiles à notre prototype.

Les éléments de bootstrap

​​​​​​​

  • Allez sur le site de bootstrap (partie donwload)
    https://v5.getbootstrap.com/docs/5.3/getting-started/download/
  • Téléchargez les fichiers compilés CSS et JS (compiled CSS et JS / download)
  • Le fichier qui nous intéresse est bootstrap-5.3.3-dist.zip
  • Unzippez le fichier bootstrap-5.3.3-dist.zip
  • Copiez les répertoires CSS et JS dans le répertoire ui / assets / bootstrap
    ​​​​​​​


Les éléments de fontawesome

  • Allez sur le site de fontawesome (partie Download)
    https://fontawesome.com/download​​​​​​​​​​​​​​
  • Download font Awesome free for the web
    ​​​​​​​
    Téléchargez les fichiers compilés CSS et JS
  • Le fichier qui nous intéresse est fontawesome-free-6.5.2-web.zip
  • Unzippez le fichier fontawesome-free-6.5.2-web.zip
  • Copiez les répertoires CSS, JS et webfonts dans le répertoire ui / assets / fontawesome

Remarque
Tous les fichiers installés ne seront pas utilisés.
Nous pouvons dans ce cas faire le ménage et ne laisser que l'essentiel.
Pour fontawesome nous ne garderons que les fichiers all.css , all.min.css et all.js et all.min.js
Vous retouverez le résultat final sur le dépôt du code source indiqué en fin de tutoriel.


Dans le code source vous retrouverez le répertoire

  • ui (code bootstrap 5)

Notre première page Bootstrap

Nous allons créer notre première page en nous inspirant des exemple proposés par bootstrap.

Nous utiliserons la page des exemples


Arbitrairement je vous donne le résultat final d'une page exemple.
​​​​​​​Les différentes parties suivent.

style body
  <style>
    body {
      padding-top: 3.5rem;
      font-family: "Roboto", sans-serif;
    }
  </style>
style header
  <!-- HEADER -->
  <style>
    .navbar.navbar-dark .navbar-nav .nav-item .nav-link {
      color: white;
      font-weight: 500;
      border-top: 1px solid #09238d;
      border-bottom: 1px solid #09238d;
    }

    .navbar.navbar-dark .navbar-nav .nav-item .nav-link:hover {
      color: yellow;
      border-top: 1px solid yellow;
      border-bottom: 1px solid yellow;
    }

    .nga-navbar {
      -webkit-box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 11px 10px 0 rgba(0, 0, 0, 0.12);
      box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 11px 10px 0 rgba(0, 0, 0, 0.12);
      background-color: #09238d;
    }

    .nga-logo {
      font-weight: 700;
    }

    .nga-logo:hover {
      color: rgba(255, 255, 255, 0.75);
    }

    .nga-btn-navbar {
      color: #fff;
      background-color: #1976d2;
      border-color: #0d6efd;
    }

    .nga-btn-navbar:hover {
      color: white;
      background-color: #0b5ed7;
      border-color: #0a58ca;
    }
  </style>
style footer
  <!-- FOOTER -->
  <style>
    .nga-footer {
      background-color: #212121;
      color: white;
    }

    .nga-footer a {
      color: white;
      text-decoration: none
    }

    .nga-footer a:hover,
    .nga-footer a:focus {
      color: yellow;
      text-decoration: underline;
    }

    .nga-footer .hint {
      background-color: #1976d2;
    }

    .nga-footer .hint:hover {
      opacity: 0.8;
    }
  </style>
style home
  <!-- HOME -->
  <style>
    .nga-card {
      display: block;
      background-color: rgba(255, 255, 255, .8);
      box-shadow: 0 1px 3px rgba(0, 0, 0, .12), 0 1px 2px rgba(0, 0, 0, .24);
      border-radius: 2px;
      transition: all .2s ease-in-out;
      cursor: pointer;
    }

    .nga-card:hover {
      box-shadow: 0 10px 20px rgba(0, 0, 0, .19), 0 6px 6px rgba(0, 0, 0, .23);
    }
  </style>
html header
  <header class="navbar navbar-expand-md navbar-dark fixed-top nga-navbar">
    <nav class="container" aria-label="Main navigation">
      <a href="" class="navbar-brand" alt="Accueil" aria-label="Ganatan">
        <img src="./assets/params/images/logo/ganatan-logo.png" srcset="./assets/params/images/logo/ganatan-logo.png,
        ./assets/params/images/logo/ganatan-logo@2x.png 2x" width="25" height="25" alt="Ganatan Logo">
        <span class="nga-logo mx-1">ganatan</span>
      </a>
      <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse"
        aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="navbarCollapse">
        <ul class="navbar-nav mx-auto">
          <li class="nav-item">
            <a class="nav-link" aria-current="page" href="">
              <i class="fas fa-home me-1"></i>Home</a>
          </li>
        </ul>
        <ul class="navbar-nav me-auto">
          <li class="nav-item">
            <a class="nav-link active" aria-current="page" href="">
              <i class="far fa-question-circle me-1"></i>About</a>
          </li>
          <li class="nav-item">
            <a class="nav-link" aria-current="page" href="">
              <i class="fas fa-envelope me-1"></i>Contact</a>
          </li>
        </ul>
        <form class="d-flex">
          <button type="button" class="btn btn-sm nga-btn-navbar me-2"><i class="fas fa-user-plus me-2"></i>Sign
            up</button>
          <button type="button" class="btn btn-sm btn-outline-light me-2"><i
              class="fas fa-sign-in-alt me-2"></i>Login</button>
        </form>
      </div>
    </nav>
  </header>
html main
  <main>

    <div class="container py-5">
      <div class="row">
        <div class="col-12 col-sm-12 col-md-12 col-lg-3 col-xl-3 text-center mb-2">
          <h1 class="h5">
            <i class="fas fa-laptop fa-lg me-2 text-primary"></i>
            angular-starter
            <i class="fas fa-mobile-alt fa-lg ms-2 text-primary"></i>
          </h1>
        </div>
        <div class="col-12 col-sm-12 col-md-12 col-lg-4 col-xl-3 text-center text-danger mb-2">
          <h2 class="h5">
            Angular 16.2.4<i class="fab fa-angular fa-lg ms-2"></i>
          </h2>
        </div>
        <div class="col-12 col-sm-12 col-md-12 col-lg-4 col-xl-3 text-center text-primary mb-2">
          <h2 class="h5">
            Bootstrap 5.3.1<i class="fab fa-bootstrap fa-lg ms-2"></i>
          </h2>
        </div>
        <div class="col-12 col-sm-12 col-md-12 col-lg-4 col-xl-3 text-center text-success mb-2">
          <h2 class="h5">
            Font Awesome 6.4.2<i class="fab fa-font-awesome-flag fa-lg ms-2"></i>
          </h2>
        </div>
      </div>
      <hr>
      <div class="row mb-2">
        <div class="col-md-12 text-center mb-4">
          <h3 class="h5">Features<i class="fas fa-list ms-2"></i></h3>
        </div>
      </div>
      <div class="row pt-2">
        <div class="col-12 col-sm-6 col-md-4 col-lg-4 col-xl-3 mb-2">
          <div class="nga-card bg-light mb-3">
            <a routerLink="/bootstrap">
              <div class="card-header">
                <div class="row">
                  <div class="col-10 col-xl-10">
                    <h5 class="card-title">Bootstrap</h5>
                  </div>
                  <div class="col-2 col-xl-2">
                    <i class="fab fa-bootstrap fa-lg text-primary"></i>
                  </div>
                </div>
              </div>
              <div class="card-body">
                <p class="card-text">How to use Buttons, Alerts, Pagination, Tables, Collapses</p>
              </div>
            </a>
          </div>
        </div>
        <div class="col-12 col-sm-6 col-md-4 col-lg-4 col-xl-3 mb-2">
          <div class="nga-card bg-light mb-3">
            <div class="card-header">
              <div class="row">
                <div class="col-10 col-xl-10">
                  <h5 class="card-title">Services</h5>
                </div>
                <div class="col-2 col-xl-2">
                  <i class="fas fa-handshake fa-lg text-primary"></i>
                </div>
              </div>
            </div>
            <div class="card-body">
              <p class="card-text">Use services to view a playlist and a youtube player</p>
            </div>
          </div>
        </div>
        <div class="col-12 col-sm-6 col-md-4 col-lg-4 col-xl-3 mb-2">
          <div class="nga-card bg-light mb-3">
            <div class="card-header">
              <div class="row">
                <div class="col-10 col-xl-10">
                  <h5 class="card-title">Components</h5>
                </div>
                <div class="col-2 col-xl-2">
                  <i class="far fa-clone  fa-lg text-primary"></i>
                </div>
              </div>
            </div>
            <div class="card-body">
              <p class="card-text">Channel component with Input, Output and Event Emitter</p>
            </div>
          </div>
        </div>
        <div class="col-12 col-sm-6 col-md-4 col-lg-4 col-xl-3 mb-2">
          <div class="nga-card bg-light mb-3">
            <div class="card-header">
              <div class="row">
                <div class="col-10 col-xl-10">
                  <h5 class="card-title">Reactive Forms</h5>
                </div>
                <div class="col-2 col-xl-2">
                  <i class="far fa-file-alt fa-lg text-primary"></i>
                </div>
              </div>
            </div>
            <div class="card-body">
              <p class="card-text">A model-driven approach to handling form inputs</p>
            </div>
          </div>
        </div>
        <div class="col-12 col-sm-6 col-md-4 col-lg-4 col-xl-3 mb-2">
          <div class="nga-card bg-light mb-3">
            <div class="card-header">
              <div class="row">
                <div class="col-10 col-xl-10">
                  <h5 class="card-title">Template Driven Forms</h5>
                </div>
                <div class="col-2 col-xl-2">
                  <i class="far fa-file-alt fa-lg text-primary"></i>
                </div>
              </div>
            </div>
            <div class="card-body">
              <p class="card-text">Forms are the mainstay of business applications</p>
            </div>
          </div>
        </div>
      </div>
    </div>

  </main>

Intégration de bootstrap dans angular

Passons maintenant à la partie logique.
Nous allons faire fonctionner cette page home dans notre projet Angular de base.

Tout d'abord il nous faut rajouter les librairies nécessaires.
On utilise pour cela npm (node package manager) le gestionnaire de dépendances de Nodes.js​​​​​

Pour bootstrap on suivra les conseils sur le site officiel.
https://v5.getbootstrap.com/docs/5.1/getting-started/download/

# Rajout des dépendances dans package.json
npm install --save bootstrap
npm install --save @fortawesome/fontawesome-free

Comme nous l'avons vu dans le tutoriel Démarrer avec angular nous modifierons les descripteurs de version de dépendances.

Concernant les dépendances et leur version la documentation npm est la suivante
https://docs.npmjs.com/files/package.json#dependencies

Ce qui nous donnera le résultat suivant.

package.json
    "@fortawesome/fontawesome-free": "6.5.2",
    "bootstrap": "5.3.3",
    "rxjs": "7.8.1",
    "tslib": "2.6.2",
    "zone.js": "0.14.2"

Mise à jour

Réutilisons donc les éléments de notre prototype.
Copiez tout le répertoire params de notre prototype dans notre application angular au niveau de src/assets

Nous allons modifier le fichier angular.json afin d'appeler les fichiers nécessaires au fonctionnement de nos pages html.

Fichiers de mise en forme css

  • index.css (spécifique à notre projet via params)
  • all.min.css (spécifique à fontawesome via node_modules)
  • bootstrap.min.css (spécifique à bootstrap via node_modules)


Fichiers des scripts javascript

angular.json
        "build": {
          "builder": "@angular-devkit/build-angular:application",
          "options": {
            "outputPath": "dist/angular-starter",
            "index": "src/index.html",
            "browser": "src/main.ts",
            "polyfills": [
              "zone.js"
            ],
            "tsConfig": "tsconfig.app.json",
            "assets": [
              "src/favicon.ico",
              "src/assets"
            ],
            "styles": [
              "node_modules/@fortawesome/fontawesome-free/css/all.min.css",
              "node_modules/bootstrap/dist/css/bootstrap.min.css",
              "src/assets/params/css/fonts.googleapis.min.css",
              "src/styles.css"
            ],
            "scripts": [
              "node_modules/bootstrap/dist/js/bootstrap.bundle.min.js"
            ]
          },
src/style.css
body {
  padding-top: 3.5rem;
  font-family: "Roboto", sans-serif;
}

Nous allons modifier les fichiers suivants qui contiendront la nouvelle interface

  • app.component.html
  • app.component.css
  • home.component.html
  • home.component.ts
  • home.component.css
  • ​​​​​​​home.component.spec.ts
  • environment.ts
  • environment.development.ts
  • app.component.spec.ts
  • app.component.ts
  • about.html
  • signin.css
  • contact.html
  • ​​​​​​​notfound.html

Nous rajouterons les images utilisées dans le répertoire assets/params/images/logo

  • ganatan.png
src/app/app.component.html
<header class="navbar navbar-expand-md navbar-dark fixed-top nga-navbar">
  <nav class="container" aria-label="Main navigation">
    <a routerLink="/" class="navbar-brand" alt="Accueil" aria-label="Ganatan">
      <img src="./assets/params/images/logo/ganatan-logo.png" srcset="./assets/params/images/logo/ganatan-logo.png,
      ./assets/params/images/logo/ganatan-logo@2x.png 2x" width="25" height="25" alt="Logo Ganatan">
      <span class="nga-logo mx-1">ganatan</span>
    </a>
    <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse"
      aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarCollapse">
      <ul class="navbar-nav mx-auto">
        <li class="nav-item">
          <a class="nav-link" aria-current="page" routerLink="/">
            <i class="fas fa-home me-1"></i>Home</a>
        </li>
      </ul>
      <ul class="navbar-nav me-auto">
        <li class="nav-item">
          <a class="nav-link active" aria-current="page" routerLink="/about">
            <i class="far fa-question-circle me-1"></i>About</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" aria-current="page" routerLink="/contact">
            <i class="fas fa-envelope me-1"></i>Contact</a>
        </li>
      </ul>
      <form class="d-flex">
        <button type="button" class="btn btn-sm btn-primary me-2" routerLink="/signup"><i
            class="fas fa-user-plus me-2"></i>Sign up</button>
        <button type="button" class="btn btn-sm btn-outline-light me-2" routerLink="/login"><i
            class="fas fa-sign-in-alt me-2"></i>Login</button>
      </form>
    </div>
  </nav>
</header>

<main>
  <router-outlet></router-outlet>
</main>

<footer class="nga-footer">
  <div class="py-3 text-center" style="background-color: black;">
    <div class="container">
      <a href="{{ footerUrl }}">{{ footerLink }}</a>
    </div>
  </div>
</footer>
src/app/app.component.css
.navbar.navbar-dark .navbar-nav .nav-item .nav-link {
    color: white;
    font-weight: 500;
    border-top: 1px solid #09238d;
    border-bottom: 1px solid #09238d;
  }
  
  .navbar.navbar-dark .navbar-nav .nav-item .nav-link:hover {
    color: yellow;
    border-top: 1px solid yellow;
    border-bottom: 1px solid yellow;
  }
  
  .nga-navbar {
    -webkit-box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 11px 10px 0 rgba(0, 0, 0, 0.12);
    box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 11px 10px 0 rgba(0, 0, 0, 0.12);
    background-color: #09238d;
  }
  
  .nga-navbar-logo {
    font-weight: 700;
  }
  
  .nga-navbar-logo:hover {
    color: rgba(255, 255, 255, 0.75);
  }
  
  .nga-logo {
    font-weight: 700;
  }
  
  .nga-logo:hover {
    color: rgba(255, 255, 255, 0.75);
  }
  
  .nga-footer {
    background-color: #212121;
    color: white;
  }
  
  .nga-footer a {
    color: white;
    text-decoration: none
  }
  
  .nga-footer a:hover,
  .nga-footer a:focus {
    color: yellow;
    text-decoration: underline;
  }
  
  .nga-footer .hint {
    background-color: #1976d2;
  }
  
  .nga-footer .hint:hover {
    opacity: 0.8;
  }
src/app/pages/general/home/home.component.html
<div class="container py-5">
    <div class="row">
      <div class="col-12 col-sm-12 col-md-12 col-lg-3 col-xl-3 text-center mb-2">
        <h1 class="h5">
          <i class="fas fa-laptop fa-lg me-2 text-primary"></i>
          {{ name }}
          <i class="fas fa-mobile-alt fa-lg ms-2 text-primary"></i>
        </h1>
      </div>
      <div class="col-12 col-sm-12 col-md-12 col-lg-4 col-xl-3 text-center text-danger mb-2">
        <h2 class="h5">
          {{ version }}<i class="fab fa-angular fa-lg ms-2"></i>
        </h2>
      </div>
      <div class="col-12 col-sm-12 col-md-12 col-lg-4 col-xl-3 text-center text-primary mb-2">
        <h2 class="h5">
          {{ bootstrap }}<i class="fab fa-bootstrap fa-lg ms-2"></i>
        </h2>
      </div>
      <div class="col-12 col-sm-12 col-md-12 col-lg-4 col-xl-3 text-center text-success mb-2">
        <h2 class="h5">
          {{ fontawesome }}<i class="fab fa-font-awesome-flag fa-lg ms-2"></i>
        </h2>
      </div>
    </div>
    <hr>
    <div class="row mb-2">
      <div class="col-md-12 text-center mb-4">
        <h3 class="h5">Features<i class="fas fa-list ms-2"></i></h3>
      </div>
    </div>
    <div class="row pt-2">
      <div class="col-12 col-sm-6 col-md-4 col-lg-4 col-xl-3 mb-2">
        <div class="card nga-card bg-light mb-3">
          <a routerLink="/bootstrap">
            <div class="card-header">
              <div class="row">
                <div class="col-10 col-xl-10">
                  <h4 class="card-title h5">Bootstrap</h4>
                </div>
                <div class="col-2 col-xl-2">
                  <i class="fab fa-bootstrap fa-lg text-primary"></i>
                </div>
              </div>
            </div>
            <div class="card-body">
              <p class="card-text">How to use Buttons, Alerts, Pagination, Tables, Collapses</p>
            </div>
          </a>
        </div>
      </div>
      <div class="col-12 col-sm-6 col-md-4 col-lg-4 col-xl-3 mb-2">
        <div class="card nga-card bg-light mb-3">
          <div class="card-header">
            <div class="row">
              <div class="col-10 col-xl-10">
                <h4 class="card-title h5">Services</h4>
              </div>
              <div class="col-2 col-xl-2">
                <i class="fas fa-handshake fa-lg text-primary"></i>
              </div>
            </div>
          </div>
          <div class="card-body">
            <p class="card-text">Use services to view a playlist and a youtube player</p>
          </div>
        </div>
      </div>
      <div class="col-12 col-sm-6 col-md-4 col-lg-4 col-xl-3 mb-2">
        <div class="card nga-card bg-light mb-3">
          <div class="card-header">
            <div class="row">
              <div class="col-10 col-xl-10">
                <h4 class="card-title h5">Components</h4>
              </div>
              <div class="col-2 col-xl-2">
                <i class="far fa-clone  fa-lg text-primary"></i>
              </div>
            </div>
          </div>
          <div class="card-body">
            <p class="card-text">Channel component with Input, Output and Event Emitter</p>
          </div>
        </div>
      </div>
      <div class="col-12 col-sm-6 col-md-4 col-lg-4 col-xl-3 mb-2">
        <div class="card nga-card bg-light mb-3">
          <div class="card-header">
            <div class="row">
              <div class="col-10 col-xl-10">
                <h4 class="card-title h5">Reactive Forms</h4>
              </div>
              <div class="col-2 col-xl-2">
                <i class="far fa-file-alt fa-lg text-primary"></i>
              </div>
            </div>
          </div>
          <div class="card-body">
            <p class="card-text">A model-driven approach to handling form inputs</p>
          </div>
        </div>
      </div>
      <div class="col-12 col-sm-6 col-md-4 col-lg-4 col-xl-3 mb-2">
        <div class="card nga-card bg-light mb-3">
          <div class="card-header">
            <div class="row">
              <div class="col-10 col-xl-10">
                <h4 class="card-title h5">Template Driven Forms</h4>
              </div>
              <div class="col-2 col-xl-2">
                <i class="far fa-file-alt fa-lg text-primary"></i>
              </div>
            </div>
          </div>
          <div class="card-body">
            <p class="card-text">Forms are the mainstay of business applications</p>
          </div>
        </div>
      </div>
    </div>
  </div>
src/app/pages/general/home/home.component.ts
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterLink, RouterOutlet } from '@angular/router';

import { environment } from '../../../../environments/environment';

@Component({
  selector: 'app-home',
  standalone: true,
  imports: [CommonModule, RouterLink, RouterOutlet],
  templateUrl: './home.component.html',
  styleUrl: './home.component.css'
})
export class HomeComponent {
  name = environment.application.name;
  version = environment.application.version;
  bootstrap = environment.application.bootstrap;
  fontawesome = environment.application.fontawesome;
}
src/app/pages/general/home/home.component.css
.nga-card {
    display: block;
    background-color: rgba(255, 255, 255, .8);
    box-shadow: 0 1px 3px rgba(0, 0, 0, .12), 0 1px 2px rgba(0, 0, 0, .24);
    border-radius: 2px;
    transition: all .2s ease-in-out;
    cursor: pointer;
  }
  
  .nga-card:hover {
    transform: translateY(-3px);
    box-shadow: 0 10px 20px rgba(0, 0, 0, .19), 0 6px 6px rgba(0, 0, 0, .23);
  }
  
  .nga-card a {
    color: black;
    text-decoration: none;
  }
  
  .nga-card a:hover {
    color: #0d6efd;
    text-decoration: none;
  }
  
src/app/pages/general/home/home.component.spec.ts
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { HomeComponent } from './home.component';
import { RouterTestingModule } from '@angular/router/testing';

describe('HomeComponent', () => {
  let component: HomeComponent;
  let fixture: ComponentFixture<HomeComponent>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [HomeComponent, RouterTestingModule]
    })
      .compileComponents();

    fixture = TestBed.createComponent(HomeComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});
src/environments/environments.ts
export const environment = {
    application:
    {
      name: 'angular-bootstrap',
      version: 'Angular 18.0.2',
      bootstrap: 'Bootstrap 5.3.3',
      fontawesome: 'Font Awesome 6.5.2',
    }
  };
src/environments/environment.development.ts
export const environment = {
    application:
    {
      name: 'angular-bootstrap',
      version: 'Angular 18.0.2',
      bootstrap: 'Bootstrap 5.3.3',
      fontawesome: 'Font Awesome 6.5.2',
    }
  };
src/app/app.component.spec.ts
import { TestBed } from '@angular/core/testing';
import { AppComponent } from './app.component';
import { RouterTestingModule } from '@angular/router/testing';

describe('AppComponent', () => {
  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [AppComponent, RouterTestingModule],
    }).compileComponents();
  });

  it('should create the app', () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.componentInstance;
    expect(app).toBeTruthy();
  });

  it(`should have the 'angular-routing' title`, () => {
    const fixture = TestBed.createComponent(AppComponent);
    const app = fixture.componentInstance;
    expect(app.title).toEqual('angular-routing');
  });

});
src/app/app.component.ts
import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterLink, RouterOutlet } from '@angular/router';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [CommonModule, RouterLink, RouterOutlet],
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent implements OnInit {
  title = 'angular-routing';
  footerUrl = 'https://www.ganatan.com';
  footerLink = 'www.ganatan.com';
  ngOnInit(): void {

    const navMain = document.getElementById('navbarCollapse');
    if (navMain) {
      navMain.onclick = function onClick() {
        if (navMain) {
          navMain.classList.remove("show");
        }
      }
    }
  }

}  
src/app/pages/general/about/about.html
<div class="row">
  <div class="col-12 col-sm-12 col-md-3 col-lg-3 col-xl-3">
    <p class="text-center">about works!</p>
    <ul>
      <li><a routerLink="/about/experience">experience</a></li>
      <li><a routerLink="/about/skill">skill</a></li>
    </ul>
  </div>
  <div class="col-12 col-sm-12 col-md-9 col-lg-9 col-xl-9">
    <router-outlet></router-outlet>
  </div>
</div>
src/app/pages/general/contact/contact.html
<div class="row">
  <div class="col-12 col-sm-12 col-md-3 col-lg-3 col-xl-3">
    <p class="text-center">contact works!</p>
    <ul>
      <li><a routerLink="/contact/mailing">Mailing</a></li>
      <li><a routerLink="/contact/map">Map</a></li>
      <li><a routerLink="/contact/website">Website</a></li>
    </ul>
  </div>
  <div class="col-12 col-sm-12 col-md-9 col-lg-9 col-xl-9">
    <router-outlet></router-outlet>
  </div>
</div>
src/app/pages/general/signup/signup.html
<p class="text-center">signup works!</p>
src/app/pages/general/not-found/not-found.html
<p class="text-center">not-found works!</p>

Composants Bootstrap

Le projet final intègre un module permettant de tester les composants de Bootstrap.

Le code étant trop long je ne l'indique pas dans ce tutoriel.
Néanmoins le source complet est disponible sur Github.


Il est rajouté via le routing dans les fichiers suivants

app.routes.ts
  {
    path: 'bootstrap',
    loadChildren: () => import('./pages/application/example-bootstrap/tutorial.module')
      .then(mod => mod.TutorialModule)
  },

Tests

Il ne reste plus qu'à tester les différents scripts Angular.

# Développement
npm run start
http://localhost:4200/

# Tests
npm run test

# Compilation
npm run build

Erreurs de compilation

La compilation va générer une erreur.
La raison notre code CSS dépasse une certaine taille préconisée dans les paramètres.

Les paramètres sont contenus dans le fichier angular.json.
Ces paramètres sont restrictifs à mon sens il suffit de les modier pour supprimer le warning

Pour le bundle initial le paramètre maximumWarning est par défaut à 500kb
Nous utiliserons maximumWarning à 1mb

Pour les autres composants l​​​​​​Le paramètre maximumWarning est par défaut à 2kb
Nous utiliserons maximumWarning à 4kb
​​​​​​​

angular.json
"production": {
  "budgets": [
    {
      "type": "initial",
      "maximumWarning": "1mb",
      "maximumError": "1mb"
    },
    {
      "type": "anyComponentStyle",
      "maximumWarning": "4kb",
      "maximumError": "4kb"
    }
  ],

Code Source

En suivant chacun des conseils que je vous ai donnés dans ce guide vous obtenez au final un code source Angular.

Le code source obtenu à la fin de ce tutoriel est disponible sur github
https://github.com/ganatan/angular-react-bootstrap

Si le code source vous plait un star sur github et c'est parti.​​​​​​​

Un star et un guerrier heureux ?


L' étape suivante va nous permettre d'améliorer notre structure.
Le tutoriel complet est à l'adresse suivante

Les étapes suivantes vous permettront d'obtenir une application prototype.

Les étapes suivantes vous permettront d'améliorer ce prototype​​​​​​​

​​​​​​​
Cette dernière étape permet d'obtenir un exemple d'application

Le code source de cette application finale est disponible sur GitHub
https://github.com/ganatan/angular-app

 

Comment créer une application From scratch ?

Créez votre compte ganatan

Téléchargez gratuitement vos guides complets

Démarrez avec angular CLI Démarrez avec angular CLI

Gérez le routing Gérez le routing

Appliquez le Lazy loading Appliquez le Lazy loading

Intégrez Bootstrap Intégrez Bootstrap


Utilisez Python avec Angular Utilisez Python avec Angular

Utilisez Django avec Angular Utilisez Django avec Angular

Utilisez Flask avec Angular Utilisez Flask avec Angular

Ganatan site Web avec Angular