How do I use nested iterators with Mustache.js or Handlebars.js?

后端 未结 6 1770
后悔当初
后悔当初 2020-12-24 01:52

I would like to use handlebars.js or mustache.js to iterate over a list of families, and then iterate over that family\'s members. Inside of both loops, I want to display pr

相关标签:
6条回答
  • 2020-12-24 01:57

    Great answer @maxbeatty.

    I just wanted to add another example if anyone have the same problem and can't understand the above solution.

    First I have one dimensional array which I wanted to split on every 4 elements:

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

    Now if we pass jagged into our view we can iterate it like that:

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

    If we have our initial array filled with objects:

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

    Then in our template we'll have:

    <ul>
    {{#jagged}}
        <li>
            <ul>
                {{#dummyKey}}
                <li>{{key1}} - {{key2}}</li>
                {{/dummyKey}}
            </ul>
        </li>
    {{/jagged}}
    </ul>
    
    0 讨论(0)
  • 2020-12-24 01:58

    For a dataset like below:

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

    following will work in mustachejs:

    <tbody>
        {{#rows}}
        <tr>
            {{#.}}
            <td>{{.}}</td>
            {{/.}}
        </tr>
        {{/rows}}
    </tbody>
    
    0 讨论(0)
  • 2020-12-24 02:00

    I was looking for the same issue using mustache and the answers were given for handlebars, and the ones for mustache required extra JS, I know it is old but I'll add my working example just in case somebody else needs it. Cheers!

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

    TEMPLATE:

    {{#experience}}
            <h2>{{company}}</h2>
            <div class="position">{{position}}</div>
            <div class="occupazione">Responsabilities</div>
                <ul>
                {{#tasks}}
                <li>{{.}}</li>
                {{/tasks}}
                </ul>
     {{/experience}}
    
    0 讨论(0)
  • 2020-12-24 02:01

    You can reference the parent loop variable and index with the ../ operator:

    {{#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}}
    
    0 讨论(0)
  • 2020-12-24 02:08

    You can nest sections easily with lists of objects. Use a data structure where families is a list that has an object members that has a list of any objects (or even more lists)like:

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

    You would be able to populate a template like:

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

    jsFiddle is currently down so here's the full working HTML with 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>
    
    0 讨论(0)
  • 2020-12-24 02:13

    Sorry I'm a little late in the game here. The accepted answer is great but I wanted to add an answer that I think is also useful, especially if you are iterating over simple row/column arrays.

    When you're working with nested handlebar paths, you can use ../ to refer to the parent template context (see here for more information).

    So for your example, you could do:

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

    This was especially useful for me because I was making a grid and I wanted to give each square a class name corresponding to its row and column position. So if rows and columns, simply return arrays, I can do this:

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

    Update

    This solution is for Handlebars. A comment below explains why it will not work in Mustache.

    0 讨论(0)
提交回复
热议问题