Angular, utilisation d’un routeur

J’aimerais pouvoir afficher au choix, dans ma webapp, les actualitĂ©s ou les “coups de cƓur” en cliquant sur un lien et ça sans recharger ma page et sans que l’état des autres composants ne soient impactĂ©s (mon formulaire de saisie ou ma liste de livres).

Pour cela il existe dans Angular le composant nRoute et nous allons voir comment nous en servir.

Pré-requis: avoir lu les articles précédents:

Préparation

Nous avons besoin d’une nouvelle dĂ©pendance : angular-route.min.js

Donc modifiez votre fichier bower.json de la maniĂšre suivante:

{
  "name": "books",
  "version": "0.0.0",
  "dependencies": {
    "angular" : "1.2.16",
    "angular-resource" : "1.2.16",
    "angular-route": "1.2.16",
    "uikit" : "2.6.0"
  }
}

Et lancez la commande bower update pour télécharger dans votre projet angular-route.

Ensuite dans la page index.html ajoutez en bas de page avec les autres définitions de script, la définition suivante:

<script src="bower_components/angular-route/angular-route.min.js"></script>

Qu’est qu’un routeur selon Angular?

Un routeur dans Angular est un composant qui est capable de dĂ©tecter la modification d’une url par une saisie dans la zone d’url du navigateur ou par le biais d’un click sur un lien et de dĂ©clencher une action en fonction et mettre Ă  jour le chargement d’une vue par le biais de la directive ng-view. C’est Ă  dire, si vous avez dans votre page html un tag comme celui-ci <div ng-view></div>, le routeur pourra non seulement dĂ©clencher une action, mais aussi charger un template Ă  l’intĂ©rieur de ce tag (de la mĂȘme maniĂšre que la directive ng-include). Pas clair?

Ok, rien de mieux qu’un exemple, alors.

Modifions légÚrement notre IHM

Modifions index.html comme suit:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>livres</title>
    <link rel="stylesheet" href="bower_components/uikit/dist/css/uikit.almost-flat.min.css" />

  </head>

  <body ng-app="booksApp" style="padding: 10px">

Insérez la liste ci-dessous :

    <div>
      <ul class="uk-breadcrumb">
        <li><a href="# /actualites">Actualités</a></li>
        <li><a href="# /coupsdecoeur">Coup de coeur</a></li>
      </ul>
    </div>

Remarquez de quelle maniĂšre sont renseignĂ©es les attributs href : on fait prĂ©cĂ©der l’url par # /.

    <div class="uk-container uk-container-center">

      <div class="uk-grid" ng-controller="MainCtrl">

        <div class="uk-width-4-10">

          <div class="uk-panel" ng-include="'books/bookForm.html'" onload="whenFormIsLoaded()"></div>

        </div>

        <div class="uk-width-6-10">

          <div class="uk-panel" ng-include="'books/booksList.html'" onload="whenListIsLoaded()"></div>

        </div>
      </div>

Ajoutez cette balise:

      <div ng-view></div>

Et le reste ne change pas:

    </div>

    <script src="bower_components/angular/angular.min.js"></script>
    <script src="bower_components/angular-resource/angular-resource.min.js"></script>
    <script src="bower_components/angular-route/angular-route.min.js"></script>
    <script src="js/main.js"></script>

  </body>
</html>

Notre 1er routeur

ngRoute

Commençons par ajouter la dépendance ngRoute à notre module principal

var booksApp = angular.module("booksApp", ["ngResource", "ngRoute"]);

Puis définissons notre routeur et son fonctionnement avec la méthode config de notre module principal en lui passant en paramÚtre $routeProvider:

booksApp.config(["$routeProvider",
  function($routeProvider) {

    $routeProvider.
      when('/actualites', {
        templateUrl: "templates/actualites.html",
        controller: "ActualitesCtrl"
      })
      .when('/coupsdecoeur', {
        templateUrl: "templates/coupsdecoeur.html",
        controller: "CoupsDeCoeurCtrl"
      })
      .otherwise({
        redirectTo: "/"
      })

  }
]);

Que venons nous de faire? A chaque fois que je cliquerais sur <a href="# /actualites">ActualitĂ©s</a> le fichier "templates/actualites.html" sera chargĂ© dans <div ng-view></div>et le contrĂŽleur "ActualitesCtrl" sera appelĂ©. De la mĂȘme maniĂšre, lorsque je cliquerais sur <a href="# /coupsdecoeur">Coup de coeur</a>le fichier "templates/coupsdecoeur.html" sera chargĂ© dans <div ng-view></div>et le contrĂŽleur "CoupsDeCoeurCtrl" sera appelĂ©.

A noter: si dans la barre d’url du navigateur vous saisissez http://localhost:3000/# /actualites ou http://localhost:3000/# /coupsdecoeur, les actions dĂ©crites ci-dessus seront dĂ©clenchĂ©es de la mĂȘme façon (sans rechargement de page), ce qui vous permet de bookmarquer l’état de votre webapp (par exemple, avoir un lien direct sur l’état qui affiche les actualitĂ©s).

DĂ©finissons nos templates

Créez un sous-répertoire templates avec 2 fichiers actualites.html et coupsdecoeur.html:

votre_projet/
├── public/
|   ├── bower_components/ /* angular est par ici */
|   ├── js/      
|   |    └── main.js
|   ├── books/ 
|   |    ├── bookForm.html
|   |    └── booksList.html  
|   ├── templates/ 
|   |    ├── actualites.html
|   |    └── coupsdecoeur.html      
|   └── index.html
|

Avec les contenus suivants:

actualites.html

<h2>{{title}}</h2>
 <ul ng-repeat="new in news">
   <li>{{new.title}}</li>
 </ul>

coupsdecoeur.html

<h2>{{title}}</h2>
<ul ng-repeat="item in items">
  <li>{{item.title}}</li>
</ul>

Et enfin, 


Écrivons les contrîleurs correspondants

Donc dans /public/js/main.js, ajoutons les contrĂŽleurs suivants

ActualitesCtrl

var ActualitesCtrl = booksApp.controller("ActualitesCtrl", function($scope) {
  $scope.title = "Actualités";
  $scope.news = [
      { title:"Un nouveau Stephen King Ă  venir?" }
    , { title:"Le Kindle paperwhite est juste une turie" }
    , { title:"Le format epub 3 en détail" }
  ];
});

CoupsDeCoeurCtrl

var CoupsDeCoeurCtrl = booksApp.controller("CoupsDeCoeurCtrl", function($scope) {
  $scope.title = "Coups de Coeur";
  $scope.items = [
      { title:"Game of Thrones" }
    , { title:"Bilbo le Hobbit" }
    , { title:"Le sorcier de TerreMĂšre" }
  ];
});

Vous pouvez maintenant tester votre webapp:

Passer des paramĂštres aux urls

Il est tout à fait possible de passer des paramùtres via l’url. Par exemple, ajoutez la route suivante au routeur:

.when('/addition/:a/:b', {
    templateUrl: "templates/addition.html",
    controller: "AdditionCtrl"
})

Créez le contrÎleur AdditionCtrl:

var AdditionCtrl = booksApp.controller("AdditionCtrl", function($scope, $routeParams) {
  $scope.result = parseInt($routeParams['a']) + parseInt($routeParams['b']);
});

Créez rapidement un template templates/addition.html:

<h1>{{result}}</h1>

Maintenant vous pouvez faire des additions de cette maniĂšre : http://localhost:3000/# /addition/5/60

Alors je trouve quelques limitations Ă  ce routeur, j’aurais aimĂ© pouvoir utiliser plusieurs routeurs et plusieurs ng-view, mais je pense qu’il faut que j’apprenne encore Ă  l’utiliser. J’ai vu qu’il existait des directives angular dans des projets externes qui le permettait. Nous le verrons peut-ĂȘtre plus tard.

Le prochain tuto sur Angular sera probablement sur la maniùre d’organiser son code, ensuite nous parlerons des tests, et aprùs 
 Nous verrons bien.

A suivre 


blog comments powered by Disqus

Related posts