Les liaisons (ngModel)
Nous allons maintenant introduire un peu d'interaction à nos pages.
Imaginez que vous entrez une valeur dans une zone de texte et que cette
valeur est utilisée en temps réel pour modifier le DOM. C'est ce que
nous allons réaliser à présent.
Directive ngModel
La directive ngModel permet de créer une liaison avec une zone de saisie. Voici un exemple (JSFiddle) :
<div ng-app> <input id="nom" type="text" ng-model="nom"> <h1>Bonjour {{nom}} !</h1> </div>
Avec la directive ngModel on a fait une liaison entre
la zone de texte et une variable située dans le modèle (en fait le scope
comme nous le verrons bientôt) qui a le même nom que celui prévu pour
la directive. Autrement dit il est créé une variable nom
dans le modèle. L'expression située dans la balise h1 est liée à cette
variable et affiche sa valeur et se raffraichit dès que celle-ci change.
Au final l'expression est mise à jour instantanément lorsque la valeur
de la zone de texte est modifiée.
Case à cocher
La directive ngModel peut s'appliquer à tout contrôle. Voici un exemple avec des cases à cocher (JSFiddle) :
<div ng-app> <form ng-init="valeur1=true; valeur2=false"> Valeur1 : <input type="checkbox" ng-model="valeur1"> {{valeur1}}<br> Valeur2 : <input type="checkbox" ng-model="valeur2"> {{valeur2}} </form> </div>
On initialise les variables valeur1 et valeur2 avec la directive ngInit.
Remarquez que la liaison est bidirectionnelle parce que la case qui
concerne la valeur1 se retrouve cochée au départ. Ensuite la
modification de la valeur de chaque case est immédiatement reportée dans
la valeur de la variable correspondante.
Select
La directive ngModel peut s'appliquer aussi à un contrôle select, c'est juste un peu plus délicat à mettre en oeuvre. Prenons le cas d'une liste de ville (JSFiddle) :
<div ng-app> <div ng-init="villes=['Paris','Lyon','Marseille','Toulouse']"> <select ng-model="valeur" ng-options="villes.indexOf(v) as v for v in villes"> <option value="">-- Choisissez une ville --</option> </select> Valeur de l'option : {{valeur}} </div> </div>
On initialise le tableau des noms de villes avec la directive ngInit. Ensuite la directive ngOptions permet de remplir la liste avec les valeurs du tableau des villes. La directive ngModel sert de liaison pour la valeur du choix, ici des nombres.
On vient de voir que la directive ngModel peut s'appliquer aussi à un contrôle select. Voyons un autre exemple, cette fois nous allons utiliser une expression pour changer une classe (JSFiddle) :
Je vous ai dit qu'AngularJS respecte le modèle MVC, pour le moment on a rien vu de tel ! On a juste utilisé des procédures "magiques" pour obtenir des résultats. Pour rappel le modèle MVC est composé de ces 3 entités :
Reprenons ce code qui fait une liaison entre un contrôle et un affichage :
On vient de voir que la directive ngModel peut s'appliquer aussi à un contrôle select. Voyons un autre exemple, cette fois nous allons utiliser une expression pour changer une classe (JSFiddle) :
<div ng-app> <label for="texte">Choisissez la classe :</label> <select ng-model="classe" ng-init="classe='noir'"> <option>noir</option> <option>rouge</option> <option>vert</option> <option>bleu</option> <option>jaune</option> </select> <button type="button" class="{{classe}}">Classe "{{classe}}" </button> </div>On a une liste avec des noms de classes. La directive ngModel établit une liaison entre la valeur sélectionnée et la classe appliquée au bouton. La valeur initiale de la liste est fixée grâce à la directive ngInit.
Le scope
Je vous ai dit qu'AngularJS respecte le modèle MVC, pour le moment on a rien vu de tel ! On a juste utilisé des procédures "magiques" pour obtenir des résultats. Pour rappel le modèle MVC est composé de ces 3 entités :
- Le modèle qui est chargée de contenir les données, donc l'état de l'application
- La vue qui est chargée d'afficher les informations pour l'utilisateur
- Le contrôleur qui est chargé d'établir la relation entre le modèle et la vue, c'est un peu le chef d'orchestre.
Reprenons ce code qui fait une liaison entre un contrôle et un affichage :
<div ng-app> <input id="nom" type="text" ng-model="nom"> <h1>Bonjour {{nom}} !</h1> </div>Si vous avez la curiosité de regarder le code généré vous allez trouver cela :
<div class="ng-scope" ng-app=""> <input class="ng-pristine ng-valid" id="nom" ng-model="nom" ng-init="nom='Toto'" type="text"> <h1 class="ng-binding">Bonjour Toto !</h1> </div>
On voit que quelques classes sont apparues : ng-scope, ng-pristine, ng-valid et ng-binding. Ces classes ont été créées lors de la compilation du code par AngularJS. Mais ce qu'on ne voit pas c'est qu'il a aussi été créé un scope. C'est un objet qui a pour fonction de :
- observer toute modification du modèle
- offrir un contexte d'exécution pour les expressions
Il est organisé de façon hiérarchique un peu à l'image du DOM. Si
nous observons notre exemple au démarrage nous avons la création d'un
scope racine. On peut le trouver en utilisant l'extension Batarang des outils de développement de Chrome :
$id: "003" $parent: null $root: h __private__: Object nom: "Toto" this: h __proto__: Object
On voit une propriété nom qui a pour valeur "Toto". Si
vous explorez cet objet vous pourrez trouver d'autres informations comme
par exemple les watchers. Mais il n'est pas très utile de fouiller tout
ça étant donné que les scopes sont automatiquement créés ! On aura
l'occasion d'explorer les scopes dans une phase ultérieure avec une
application plus fournie. Si vous voulez déjà explorer un peu plus ce
domaine vous pouvez consulter la documentation.
Aucun commentaire:
Enregistrer un commentaire