简体   繁体   中英

How to iterate over array of objects in Handlebars?

This might seem a silly question but I can't seem to find the answer anywhere.

I'm hitting this Web API that returns an array of objects in JSON format:

对象数组

Handlebars docs shows the following example:

<ul class="people_list">
  {{#each people}}
  <li>{{this}}</li>
  {{/each}}
</ul>

In the context of:

{
  people: [
    "Yehuda Katz",
    "Alan Johnson",
    "Charles Jolley"
  ]
}

In my case I don't have a name for the array, it's just the root object of the response. I've tried using {{#each}} with no luck.

First time using Handlebars... What am I missing?

UPDATE

Here's a simplified fiddle to show you what I'm asking: http://jsfiddle.net/KPCh4/2/

Does handlebars require the context variable to be an object and not an array?

You can pass this to each block. See here: http://jsfiddle.net/yR7TZ/1/

{{#each this}}
    <div class="row"></div>
{{/each}}

This fiddle has both each and direct json. http://jsfiddle.net/streethawk707/a9ssja22/ .

Below are the two ways of iterating over array. One is with direct json passing and another is naming the json array while passing to content holder.

Eg1: The below example is directly calling json key (data) inside small_data variable.

In html use the below code:

<div id="small-content-placeholder"></div>

The below can be placed in header or body of html:

<script id="small-template" type="text/x-handlebars-template">
    <table>
        <thead>
            <th>Username</th>
            <th>email</th>
        </thead>
        <tbody>
            {{#data}}
                <tr>
                    <td>{{username}}
                    </td>
                    <td>{{email}}</td>
                </tr>
            {{/data}}
        </tbody>
    </table>
</script>

The below one is on document ready:

var small_source   = $("#small-template").html();
var small_template = Handlebars.compile(small_source);

The below is the json:

var small_data = {
            data: [
                {username: "alan1", firstName: "Alan", lastName: "Johnson", email: "alan1@test.com" },
                {username: "alan2", firstName: "Alan", lastName: "Johnson", email: "alan2@test.com" }
            ]
        };

Finally attach the json to content holder:

$("#small-content-placeholder").html(small_template(small_data));

Eg2: Iteration using each.

Consider the below json.

var big_data = [
            {
                name: "users1",
                details: [
                    {username: "alan1", firstName: "Alan", lastName: "Johnson", email: "alan@test.com" },
                    {username: "allison1", firstName: "Allison", lastName: "House", email: "allison@test.com" },
                    {username: "ryan1", firstName: "Ryan", lastName: "Carson", email: "ryan@test.com" }
                  ]
            },
            {
                name: "users2",
                details: [
                    {username: "alan2", firstName: "Alan", lastName: "Johnson", email: "alan@test.com" },
                    {username: "allison2", firstName: "Allison", lastName: "House", email: "allison@test.com" },
                    {username: "ryan2", firstName: "Ryan", lastName: "Carson", email: "ryan@test.com" }
                  ]
            }
      ];

While passing the json to content holder just name it in this way:

$("#big-content-placeholder").html(big_template({big_data:big_data}));

And the template looks like :

<script id="big-template" type="text/x-handlebars-template">
    <table>
        <thead>
            <th>Username</th>
            <th>email</th>
        </thead>
        <tbody>
            {{#each big_data}}
                <tr>
                    <td>{{name}}
                            <ul>
                                {{#details}}
                                    <li>{{username}}</li>
                                    <li>{{email}}</li>
                                {{/details}}
                            </ul>
                    </td>
                    <td>{{email}}</td>
                </tr>
            {{/each}}
        </tbody>
    </table>
</script>

I meant in the template() call..

You just need to pass the results as an object. So instead of calling

var html = template(data);

do

var html = template({apidata: data});

and use {{#each apidata}} in your template code

demo at http://jsfiddle.net/KPCh4/4/
( removed some leftover if code that crashed )

Handlebars can use an array as the context. You can use . as the root of the data. So you can loop through your array data with {{#each .}} .

 var data = [ { Category: "General", DocumentList: [ { DocumentName: "Document Name 1 - General", DocumentLocation: "Document Location 1 - General" }, { DocumentName: "Document Name 2 - General", DocumentLocation: "Document Location 2 - General" } ] }, { Category: "Unit Documents", DocumentList: [ { DocumentName: "Document Name 1 - Unit Documents", DocumentList: "Document Location 1 - Unit Documents" } ] }, { Category: "Minutes" } ]; $(function() { var source = $("#document-template").html(); var template = Handlebars.compile(source); var html = template(data); $('#DocumentResults').html(html); });
 .row { border: 1px solid red; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/1.0.0/handlebars.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script> <div id="DocumentResults">pos</div> <script id="document-template" type="text/x-handlebars-template"> <div> {{#each .}} <div class="row"> <div class="col-md-12"> <h2>{{Category}}</h2> {{#DocumentList}} <p>{{DocumentName}} at {{DocumentLocation}}</p> {{/DocumentList}} </div> </div> {{/each}} </div> </script>

I had a similar issue I was getting the entire object in this but the value was displaying while doing #each .

Solution: I re-structure my array of object like this:

let list = results.map((item)=>{
    return { name:item.name, author:item.author }
});

and then in template file:

{{#each list}}
    <tr>
        <td>{{name }}</td>
        <td>{{author}}</td>      
    </tr>
{{/each}} 

Using this and {{this}} . See code below in node.js:

var Handlebars= require("handlebars");
var randomList= ["James Bond", "Dr. No", "Octopussy", "Goldeneye"];
var source= "<ul>{{#each this}}<li>{{this}}</li>{{/each}}</ul>";
var template= Handlebars.compile(source);
console.log(template(randomList));

Console log output:

<ul><li>James Bond</li><li>Dr. No</li><li>Octopussy</li><li>Goldeneye</li></ul>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM