IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Tutoriel pour apprendre à utiliser le framework Vue.js version 2

Les bases


précédentsommairesuivant

III. On se répète…

On a vu qu'on pouvait établir une liaison entre une propriété dans le modèle et un élément dans la vue. Mais pour le moment on a utilisé des valeurs simples : nombre ou chaîne de caractères. Dans de multiples cas on aura besoin d'afficher des valeurs contenues dans un tableau ou un objet. Comment procéder dans ce cas ? Vue.js nous propose une directive puissante et simple à utiliser pour réaliser cela.

III-A. La directive v-for

La directive v-for permet de répéter l'affichage d'un élément du DOM en fonction des valeurs contenues dans un tableau du modèle. Un petit exemple vous fera comprendre cela rapidement.

Voilà le HTML :

 
Sélectionnez
1.
2.
3.
4.
5.
<ul id="tuto">
  <li v-for="value in items">
    {{ value }}
  </li>
</ul>

Le but est de créer une liste non ordonnée. On englobe donc avec une balise ul. On prévoit la directive v-for dans la balise li qui doit être répétée, et on précise le nom de la propriété qui contient les objets. On utilise enfin mustache pour les valeurs des items.

Voilà le JavaScript :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
new Vue({
  el: '#tuto',
  data: {
    items: [
      "Je suis l'item 1",
      "Je suis l'item 2",
      "Je suis l'item 3"
    ]
  }
});

On a la propriété items qui contient un tableau de valeurs.

Avec ce rendu :

Image non disponible

Le tableau est donc parcouru, et pour chaque objet rencontré, une balise li est créée avec la valeur de l'item.

On peut également utiliser for à la place de in pour se rapprocher de la syntaxe des itérateurs.

Voici une illustration du fonctionnement :

Image non disponible

III-B. Un index

Il est souvent utile de connaître l'index de l'élément répété, et pour l'obtenir il faut ajouter la variable index. Voici un exemple :

 
Sélectionnez
<li v-for="(value, index) in fruits">
  {{ index }} => {{ value }}
</li>

Avec ce JavaScript :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
new Vue({
  el: '#tuto',
  data: {
    fruits: [
      'pomme',
      'cerise',
      'abricot'
    ]
  }
});

Et ce résultat :

Image non disponible

Le principal intérêt de connaître l'index est dans une perspective dynamique. Voici le code HTML modifié pour illustrer cela :

 
Sélectionnez
<li v-for="(value, index) in fruits" @click="getFruit(index)">
    {{ index }} => {{ value }}
</li>

On a maintenant en place la détection d'un clic. On transmet comme paramètre l'index.

Voici le JavaScript :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
new Vue({
  el: '#tuto',
  data: {
    fruits: [
      'pomme',
      'cerise',
      'abricot'
    ]
  },
  methods: {
    getFruit: function(index) {
      alert('Je suis ' + this.fruits[index]);
    }
  }
});

On a une méthode getFruit qui attend l'argument index. Selon la valeur de l'index on va extraire le bon fruit du tableau et obtenir ce genre de message :

Image non disponible

Sans cet index on ne pourrait pas localiser l'action.

Voici une illustration de ce fonctionnement :

Image non disponible

III-C. Itérer un tableau d'objets

On a vu qu'on peut créer une répétition dans le DOM avec un tableau de valeurs. Peut-on aussi le faire à partir d'un tableau d'objets ? La réponse est positive et nous allons voir comment faire avec un premier exemple.

Voici la partie HTML :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
<table class="table table-bordered">
  <caption>Personnes</caption>
  <thead>
    <tr>
     <th>Nom</th>
     <th>Prénom</th>
    </tr>
  </thead>
  <tbody id="tuto">
    <tr v-for="personne in personnes">
      <td>{{ personne.nom }}</td>
      <td>{{ personne.prenom }}</td>   
    </tr>  
  </tbody>     
</table>

La structure est en place et on va répéter des cellules avec les informations du modèle. On se réfère à la propriété personnes du modèle et aux propriétés nom et prenom.

Voici le JavaScript :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
new Vue({
  el: '#tuto',
  data: {
    personnes: [
      {nom: "Durand", prenom: "Jacques"},
      {nom: "Dupont", prenom: "Albert"},
      {nom: "Martin", prenom: "Denis"},
    ]
  }
});

On a le modèle avec toutes les personnes mémorisées (nom et prénom).

Voici le résultat à l'affichage :

Image non disponible

Voici une schématisation du fonctionnement :

Image non disponible

III-D. Et si le tableau est modifié ?

On a vu que lorsqu'on lie une propriété avec une valeur simple le changement de celle-ci est répercuté dans la vue. Qu'en est-il avec les tableaux ?

III-D-1. Les mutateurs

Toutes les méthodes qui modifient un tableau (les mutateurs) sont prises en compte. Voici les mutateurs en œuvre.

On conserve le HTML utilisé ci-dessus :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
<table class="table table-bordered">
  <caption>Personnes</caption>
  <thead>
    <tr>
     <th>Nom</th>
     <th>Prénom</th>
    </tr>
  </thead>
  <tbody id="tuto">
    <tr v-for="personne in personnes">
      <td>{{ personne.nom }}</td>
      <td>{{ personne.prenom }}</td>   
    </tr>  
  </tbody>       
</table>

Avec ce JavaScript :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
var vm = new Vue({
  el: '#tuto',
  data: {
    personnes: [
      {nom: "Durand", prenom: "Jacques"},
      {nom: "Dupont", prenom: "Albert"},
      {nom: "Martin", prenom: "Denis"},
    ]
  }
});

setTimeout(function(){vm.personnes.push({nom: "Claret", prenom: "Marcel"});}, 2000);
setTimeout(function(){vm.personnes.pop();}, 4000);
setTimeout(function(){vm.personnes.unshift({nom: "Claret", prenom: "Marcel"});}, 6000);
setTimeout(function(){vm.personnes.shift();}, 8000);
setTimeout(function(){vm.personnes.splice(1, 1, {nom: "Claret", prenom: "Marcel"});}, 10000);
setTimeout(function(){vm.personnes.sort(function (a, b) { return (a.nom > b.nom) });}, 12000);
setTimeout(function(){vm.personnes.reverse();}, 14000);

Lorsque vous chargez la page, le tableau apparaît comme présenté ci-dessus, puis toutes les deux secondes il se transforme conformément aux méthodes utilisées. Vous allez constater que le tableau de la vue suit fidèlement les changements du tableau du modèle.

III-D-2. Les accesseurs

Les accesseurs ne modifient pas un tableau mais en retournent un nouveau. Dans ce cas évidemment les modifications ne sont pas répercutées. Il faut donc remplacer l'ancien tableau par le nouveau. Prenons un nouvel exemple, le HTML est le même que ci-dessus :

Voici la partie JavaScript :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
var vm = new Vue({
  el: '#tuto',
  data: {
    personnes: [
      {nom: "Durand", prenom: "Jacques"},
      {nom: "Dupont", prenom: "Albert"},
      {nom: "Martin", prenom: "Denis"},
    ]
  }
});

setTimeout(function(){
  vm.personnes = vm.personnes.concat([
    {nom: "Claret", prenom: "Marcel"},
    {nom: "Verlou", prenom: "Gustave"}
  ]);
}, 2000);
setTimeout(function(){vm.personnes = vm.personnes.slice(1, 4);}, 4000);

On a encore une modification du tableau toutes les deux secondes. Vous remarquerez que cette fois il a fallu affecter à nouveau le tableau pour prendre en compte les modifications.

III-D-3. Modification d'un élément de tableau

Regardez maintenant cet exemple :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
var vm = new Vue({
  el: '#tuto',
  data: {
    personnes: [
      {nom: "Durand", prenom: "Jacques"},
      {nom: "Dupont", prenom: "Albert"},
      {nom: "Martin", prenom: "Denis"},
    ]
  }
});

vm.personnes[1] = {nom: "Claret", prenom: "Marcel"};

Dans ce cas le tableau ne sera pas mis à jour dans la vue.

Pour y parvenir, Vue.js propose la méthode set :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
var vm = new Vue({
  el: '#tuto',
  data: {
    personnes: [
      {nom: "Durand", prenom: "Jacques"},
      {nom: "Dupont", prenom: "Albert"},
      {nom: "Martin", prenom: "Denis"},
    ]
  }
});

Vue.set(vm.personnes, 1, {nom: "Claret", prenom: "Marcel"});

Cette fois le nouvel objet sera pris en compte !

III-E. Itérer un objet

Maintenant voyons le cas de l'itération d'un objet avec un exemple simple.

Voici le HTML :

 
Sélectionnez
1.
2.
3.
4.
5.
<ul>
  <li v-for="value in personne">
      {{ value }}
  </li>
</ul>

Et le JavaScript :

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
new Vue({
    el: '#tuto',
    data: {
        personne: {
            nom: "Durand",
            prenom: "Jacques"
        }
    }
});

On va ainsi itérer les propriétés de l'objet personne :

Image non disponible

Il est aussi possible de récupérer les clés. Voici l'exemple ci-dessus complété :

 
Sélectionnez
1.
2.
3.
4.
5.
<ul>
  <li v-for="(value, key) in personne">
      {{ key }} => {{ value }}
  </li>
</ul>

Le JavaScript est le même et voici le résultat :

Image non disponible

III-F. Un exemple

Avec tout ce que nous avons vu jusqu'à présent, nous allons pouvoir élaborer un exemple un peu plus intéressant. Disons que nous avons une liste de personnes dans un tableau. Nous voulons pour chaque personne un bouton pour la mettre à la poubelle. On a donc aussi une liste de personnes en poubelle. Dans cette poubelle nous voulons pouvoir soit rétablir la personne dans la liste des personnes, soit la supprimer complètement. Vous comprendrez sans doute mieux en faisant fonctionner l'exemple.

Voici le code complet :

 
Sélectionnez
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.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
<!DOCTYPE html>
<html lang="fr">

  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Test vue.js</title>
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
  </head>

  <body>

    <div class="container" id="tuto">
      <br>

      <div class="panel panel-primary" v-show="personnes.length">
        <div class="panel-heading">Personnes actives</div>        
        <table class="table table-bordered table-striped">
          <thead>
            <tr>
             <th class="col-sm-5">Nom</th>
             <th class="col-sm-5">Prénom</th>
             <th class="col-sm-2"></th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="(personne, index) in personnes">
              <td>{{ personne.nom }}</td>
              <td>{{ personne.prenom }}</td> 
              <td><button class="btn btn-warning btn-block" @click="supprimer(index)">Poubelle</button></td>  
            </tr>  
          </tbody>       
        </table>
        <div class="panel-footer">
          &nbsp
          <button class="button btn btn-xs btn-warning" @click="toutPoubelle">Tout à la poubelle</button>
        </div>
      </div> 

      <div class="panel panel-danger" v-show="poubelle.length">
        <div class="panel-heading">Poubelle</div>
        <table class="table table-bordered table-striped">
          <thead>
            <tr>
             <th class="col-sm-4">Nom</th>
             <th class="col-sm-4">Prénom</th>
             <th class="col-sm-2"></th>
             <th class="col-sm-2"></th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="(personne, index) in poubelle">
              <td>{{ personne.nom }}</td>
              <td>{{ personne.prenom }}</td> 
              <td><button class="btn btn-success btn-block" @click="retablir(index)">Rétablir</button></td>
              <td><button class="btn btn-danger btn-block" @click="eliminer(index)">Supprimer</button></td>    
            </tr>  
          </tbody>       
        </table>
        <div class="panel-footer">
          &nbsp
          <div class="btn-group">
            <button class="button btn btn-xs btn-success" @click="toutRetablir">Tout rétablir</button>
            <button class="button btn btn-xs btn-danger" @click="toutEliminer">Tout supprimer</button> 
          </div>
        </div>
      </div> 

    </div>

    <script src="https://unpkg.com/vue@2.0.3/dist/vue.js"></script>

    <script>

      var vm = new Vue({
        el: '#tuto',
        data: {
          personnes: [
            {nom: "Claret", prenom: "Marcel"},
            {nom: "Dupont", prenom: "Albert"},
            {nom: "Durand", prenom: "Jacques"},            
            {nom: "Martin", prenom: "Denis"},
            {nom: "Torlet", prenom: "Arthur"}            
          ],
          poubelle: []
        },
        methods: {
          supprimer: function(index) {
            this.poubelle.push(this.personnes[index]);
            this.personnes.splice(index, 1);
            this.poubelle.sort(ordonner);
          },
          retablir: function(index) {
            this.personnes.push(this.poubelle[index]);
            this.poubelle.splice(index, 1);
            this.personnes.sort(ordonner);
          },
          eliminer: function(index) {
            this.poubelle.splice(index, 1);
          },
          toutPoubelle: function() {
            this.poubelle = this.poubelle.concat(this.personnes);
            this.poubelle.sort(ordonner);
            this.personnes = [];
          },
          toutRetablir: function() {
            this.personnes = this.personnes.concat(this.poubelle);
            this.personnes.sort(ordonner);
            this.poubelle = [];
          },
          toutEliminer: function() {
            this.poubelle = [];
          }
        }
      });

      var ordonner = function (a, b) { return (a.nom > b.nom) };

    </script>

  </body>

</html>

Au départ on a la liste des personnes :

Image non disponible

Pour chaque personne on dispose d'un bouton pour la mettre à la poubelle. On a aussi un bouton pour mettre tout le monde à la poubelle. Si je clique, par exemple, sur le bouton de Dupont, j'obtiens :

Image non disponible

Le panneau de la poubelle devient visible avec Dupont présent. On dispose d'un bouton pour le rétablir et d'un autre pour le supprimer définitivement. Si on clique sur « Rétablir » on se retrouve dans la situation initiale.

Si on envoie Martin aussi à la poubelle, on se retrouve ainsi :

Image non disponible

On remarque que la liste de la poubelle s'ordonne automatiquement.

Si on envoie tout le monde à la poubelle, le premier panneau disparaît et il ne reste que la liste de la poubelle :

Image non disponible

On peut rétablir une ou toutes les personnes d'un coup. Vous avez compris le principe, je vous laisse faire des tests et analyser le code, il ne comporte que des choses que nous avons déjà vues, et c'est une bonne occasion pour réviser ce qui a été présenté lors des articles précédents.

III-G. En résumé

  • La directive v-for permet de répéter des éléments du DOM à partir de données du modèle.
  • La directive v-for génère un index pour identifier les éléments.
  • On peut itérer un tableau de valeurs ou d'objets.
  • Lorsqu'on utilise un accesseur il faut assigner de nouveau le tableau généré.
  • On dispose de la méthode set pour modifier un élément de tableau.

précédentsommairesuivant

Copyright © 2017 Laravel. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.