web-dev-qa-db-fra.com

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

Je voudrais utiliser handlebars.js ou moustache.js pour parcourir une liste de familles, puis parcourir les membres de cette famille. À l'intérieur des deux boucles, je veux afficher les propriétés des deux. Cependant, une fois que j'entre dans la deuxième itération, aucune des variables familiales 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!

34
Eric the Red

Vous pouvez facilement imbriquer des 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 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>
45
maxbeatty

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, je pense, est également utile, surtout si vous effectuez une itération sur des tableaux de lignes/colonnes simples.

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 faisais une grille et je voulais donner à chaque carré un nom de classe correspondant à sa position de ligne et de colonne. Donc, si rows et columns, renvoie 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 est pour les guidons. Un commentaire ci-dessous explique pourquoi cela ne fonctionnera pas dans Moustache.

55
Samo

Grande réponse @maxbeatty.

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

J'ai d'abord un tableau dimensionnel que je voulais diviser sur 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 notre tableau initial est 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>
5
simo

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

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

ce qui suit fonctionnera dans moustachejs:

<tbody>
    {{#rows}}
    <tr>
        {{#.}}
        <td>{{.}}</td>
        {{/.}}
    </tr>
    {{/rows}}
</tbody>
3
Haris ur Rehman

Je cherchais le même problème en utilisant la moustache et les réponses ont été données pour le guidon, et celles pour la moustache nécessitaient du JS supplémentaire, je sais que c'est ancien mais j'ajouterai mon exemple de travail au cas où quelqu'un d'autre en aurait besoin. À votre santé!

JSON:

"experience": [
     {
            "company": "Company 1",
            "position": "Graphic Designer",
            "tasks": ["Task 1", "Task 2", "Task 3"]
    },
     {
            "company": "Company 2",
            "position": "Graphic Designer",
            "tasks": ["Task 1", "Task 2", "Task 3", "Task 4", "Task 5"]
    }
]

MODÈLE:

{{#experience}}
        <h2>{{company}}</h2>
        <div class="position">{{position}}</div>
        <div class="occupazione">Responsabilities</div>
            <ul>
            {{#tasks}}
            <li>{{.}}</li>
            {{/tasks}}
            </ul>
 {{/experience}}
0
ryangus