39 votes

Comment utiliser des itérateurs imbriqués avec Mustache.js ou Handlebars.js ?

Je voudrais utiliser handlebars.js ou mustache.js pour itérer sur une liste de familles, puis sur les membres de cette famille. À l'intérieur des deux boucles, je veux afficher les propriétés des deux familles. Cependant, une fois que je suis dans la deuxième itération, aucune des variables de la famille n'est visible.

{{#each families}}
  {{#each members}}
    <p>{{ ( here I want a family name property ) }}</p>
    <p>{{ ( here I want a member name property ) }}</p>
  {{/each}}
{{/each}}

Est-ce possible ? J'apprécierais grandement toute aide !

60voto

Samo Points 3101

Désolé, je suis un peu en retard dans le jeu ici. La réponse acceptée est excellente, mais je voulais ajouter une réponse qui, à mon avis, est également utile, surtout si vous itérez sur des tableaux simples de lignes/colonnes.

Lorsque vous travaillez avec des chemins de guidon imbriqués, vous pouvez utiliser ../ pour faire référence au contexte du modèle parent ( voir ici pour plus d'informations).

Donc, pour votre exemple, vous pourriez faire :

{{#each families}}
  {{#each members}}
    <p>{{../surname}}</p>
    <p>{{given}}</p>
  {{/each}}
{{/each}}

Cela m'a été particulièrement utile car je réalisais une grille et je voulais donner à chaque carré un nom de classe correspondant à sa position en ligne et en colonne. Ainsi, si rows y columns en retournant simplement des tableaux, je peux le faire :

<tbody>
  {{#each rows}}                                                           
    <tr>
      {{#each columns}}
        <td class="{{this}}{{../this}}"></td>
      {{/each}}
    </tr>
  {{/each}}
</tbody>

Mise à jour

Cette solution concerne les guidons. Un commentaire ci-dessous explique pourquoi elle ne fonctionnera pas dans Mustache.

52voto

maxbeatty Points 4066

Vous pouvez facilement imbriquer les sections avec des listes d'objets. Utilisez une structure de données où families est une liste qui a un objet members qui a une liste de tous les objets (ou même plus de listes) comme :

{
  "families" : [
        {
          "surname": "Jones",
          "members": [
            {"given": "Jim"},
            {"given": "John"},
            {"given": "Jill"}
          ]
        },
        {
          "surname": "Smith",
          "members": [
            {"given": "Steve"},
            {"given": "Sally"}
          ]
        }
      ]
}

Vous seriez en mesure de remplir un modèle comme :

<ul>
    {{#families}}
    <li>{{surname}}
      <ul>
        {{#members}}
        <li>{{given}}</li>
        {{/members}}
      </ul>
    </li>
    {{/families}}
  </ul>

jsFiddle est actuellement en panne, voici donc le HTML complet et fonctionnel avec JS :

<!DOCTYPE html>
<head>

  <script src="http://cdnjs.cloudflare.com/ajax/libs/mustache.js/0.3.0/mustache.min.js"></script>
  <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
  <script>
    $(function() {
      var tpl = $('#fam').html(),
        data = {
          "families" : [
            {
              "surname": "Jones",
              "members": [
                {"given": "Jim"},
                {"given": "John"},
                {"given": "Jill"}
              ]
            },
            {
              "surname": "Smith",
              "members": [
                {"given": "Steve"},
                {"given": "Sally"}
              ]
            }
          ]
        },
        html = Mustache.to_html(tpl, data);

        $("#main").append(html);

    });
  </script>

</head>

<div id="main"></div>

<script type="template/text" id="fam">
  <ul>
    {{#families}}
    <li>{{surname}}
      <ul>
        {{#members}}
        <li>{{given}}</li>
        {{/members}}
      </ul>
    </li>
    {{/families}}
  </ul>
</script>

5voto

simo Points 1147

Excellente réponse @maxbeatty.

Je voulais juste ajouter un autre exemple si quelqu'un a le même problème et ne comprend pas la solution ci-dessus.

Tout d'abord, j'ai un tableau à une dimension que je veux diviser tous les 4 éléments :

// this is the one dimensional data we have from let's say a mysql query
var array = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', ...];

// think of it as [[], [], [], [], [], ...]
// but instead we'll be adding a dummy object with a dummyKey
// since we need a key to iterate on
var jagged = [];

var size = 4, // this is the size of each block
    total = array.length / block; // total count of all blocks
// slice the initial one dimensional array into blocks of 4 elements each
for (var i=0; i < total; i++) {
    jagged.push({dummyKey: array.slice(i*size, (i+1)*size)});
}

Maintenant, si nous passons jagged dans notre vue, nous pouvons l'itérer comme ça :

<ul>
{{#jagged}}
    <li>
        <ul>
            {{#dummyKey}}
            <li>{{.}}</li>
            {{/dummyKey}}
        </ul>
    </li>
{{/jagged}}
</ul>

Si nous avons notre tableau initial rempli d'objets :

var array = [{key1: 'a', 
              key2: 'b'},
             {key1: 'c', 
              key2: 'd'},
             {key1: 'e', 
              key2: 'f'},
              ...
];

Ensuite, dans notre modèle, nous aurons :

<ul>
{{#jagged}}
    <li>
        <ul>
            {{#dummyKey}}
            <li>{{key1}} - {{key2}}</li>
            {{/dummyKey}}
        </ul>
    </li>
{{/jagged}}
</ul>

4voto

hrehman Points 734

Pour un ensemble de données comme ci-dessous :

{
  rows: 
    ["1A", "1B"], 
    ["2A", "2B"], 
    ["3A", "3B"]
}

Ce qui suit fonctionnera dans mustachejs :

<tbody>
    {{#rows}}
    <tr>
        {{#.}}
        <td>{{.}}</td>
        {{/.}}
    </tr>
    {{/rows}}
</tbody>

2voto

igaster Points 152

Vous pouvez faire référence à la variable et à l'index de la boucle parent avec la fonction ../ opérateur :

{{#each families}}
  {{#each this.members}}
    <p>Current member: {{ this.name }} (this = inner loop itterator)</p>
    <p>Current family: {{ ../this.title }} (../this = parent loop itterator)</p>
    <p>Current member index: {{ @index }}</p>
    <p>Current family index: {{ @../index }}</p>
  {{/each}}
{{/each}}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X