2012-02-09 40 views
31

Me gustaría usar handlebars.js o moustache.js para recorrer una lista de familias, y luego iterar sobre los miembros de esa familia. Dentro de ambos bucles, quiero mostrar las propiedades de ambos. Sin embargo, una vez que entro en la segunda iteración, ninguna de las variables familiares está visible.¿Cómo uso los iteradores anidados con Mustache.js o Handlebars.js?

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

¿Esto es posible? ¡Agradecería enormemente cualquier ayuda!

+1

puede también añadir una muestra de los datos del objeto que está alimentando al bigote/manillar? – gonchuki

Respuesta

43

Puede anidar secciones fácilmente con listas de objetos. Utilice una estructura de datos donde families es una lista que tiene un objeto members que tiene una lista de los objetos (o incluso más listas) como:

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

Usted sería capaz de llenar una plantilla como:

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

jsFiddle está actualmente abajo así que aquí está el código HTML poder trabajar con 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> 
+2

Fiddles para [** Handlebars **] (http://jsfiddle.net/KyleMit/nL32Q/1/) y [** Bigote **] (http://jsfiddle.net/KyleMit/e3kMw/1/) – KyleMit

+1

¿Qué sucede si la matriz anterior también tiene una propiedad llamada "dada" a la que desea hacer referencia? –

+0

@DominicTobias Moustache solo le permite hacer referencia a variables del alcance actual. Puede tener una variable 'given 'en cada nivel, pero no puede acceder a las variables de los niveles principales. http://jsfiddle.net/9jpnpw7a/1/ (Los manubrios probablemente te dejarían hacer esto) – maxbeatty

5

Gran @maxbeatty respuesta.

Solo quería agregar otro ejemplo si alguien tiene el mismo problema y no puede entender la solución anterior.

En primer lugar tengo una matriz unidimensional, que quería dividir en cada 4 elementos:

// 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)}); 
} 

Ahora si pasamos jagged en nuestro punto de vista, podemos iterar de esa manera:

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

Si tenemos nuestro conjunto inicial lleno de objetos:

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

Entonces en nuestro témpo placa tendremos:

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

Lo siento, estoy un poco tarde en el juego aquí. La respuesta aceptada es excelente, pero quería agregar una respuesta que creo que también es útil, especialmente si está iterando sobre matrices simples de fila/columna.

Cuando trabaje con rutas de acceso anidadas en el manillar, puede usar ../ para referirse al contexto de la plantilla primaria (see here para obtener más información).

Así, por tu ejemplo, se puede hacer:

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

Esto era especialmente útil para mí porque yo estaba haciendo una rejilla y quería dar a cada cuadro un nombre de clase correspondiente a su posición de fila y columna. Así que si rows y columns, devuelva matrices, puedo hacer esto:

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

actualización

Esta solución es que los manillares. Un comentario a continuación explica por qué no funcionará en Moustache.

+3

ten en cuenta que esto solo funciona en los manubrios, no en el bigote. Moustache recogerá solo la variable "más cercana" con el mismo nombre en las rutas anidadas, y que yo sepa, no hay forma de acceder a una variable con el mismo nombre declarado en un nivel externo. El uso de la sintaxis '../' en una plantilla de bigote no arrojará un error, pero no recogerá ningún valor. – Pere

+0

Gracias por la aclaración. De hecho, no lo sabía. – Samo

+1

exactamente lo que estaba buscando! gracias por compartir –

1

Para un conjunto de datos, como a continuación:

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

siguiente funcionará en mustachejs:

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

que estaba buscando el mismo problema utilizando el bigote y se les dieron las respuestas para los manillares y las para bigote se requiere JS adicional, sé que es viejo, pero agregaré mi ejemplo de trabajo por si acaso alguien más lo necesita. ¡Aclamaciones!

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"] 
    } 
] 

PLANTILLA:

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