简体   繁体   中英

Return array of objects from Handlebars Helper

I'm trying to write a helper that will return an array of objects that can then be looped through. Here's what I have now:

Handlebars.registerHelper('testHelper', () => {
  return [
    { slug: 'Test', title: 'This is it!' },
    { slug: 'Test 2', title: 'This is the second it!' },
  ];
});

Using it like:

{{#entries this}}
  <a href="/{{slug}}">{{title}}</a>
{{/entries}}

And I'm receiving [object, Object] for each object in the array instead of the individual values. Please help :)

Thanks!

The way helpers in Handlebars work is a bit tricky. Instead of passing data from the helper to the main template body, you pass the portion of the template body related to the helper to the helper.

So, for example, when you do this:

{{#entries this}}
  <a href="/{{slug}}">{{title}}</a>
{{/entries}}

You are providing two things to the entries helper: 1) the current context (this) 2) some template logic to apply

Here's how the helper gets these items:

Handlebars.registerHelper('entries', (data, options) => {
  // data is whatever was provided as a parameter from caller
  // options is an object provided by handlebars that includes a function 'fn'
  //   that we can invoke to apply the template enclosed between 
  //   #entries and /entries from the main template
   :
   :
});

So, to do what you want to do:

Handlebars.registerHelper('testHelper', (ignore, opt) => {
  var data = [
    { slug: 'Test', title: 'This is it!' },
    { slug: 'Test 2', title: 'This is the second it!' },
  ];
  var results = '';
  data.forEach( (item) => {
    results += opt.fn(item);
  });
  return results;
});

The opt.fn(item) applies this portion of template:

<a href="/{{slug}}">{{title}}</a>

and the idea is to create a string (a portion of your html) that is then returned and placed into the string being formulated by your main template.

Here's a sample to show this working.

 <!DOCTYPE html> <html> <head> <title>Page Title</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/2.0.0/handlebars.js"></script> </head> <body> <script id="t" type="text/x-handlebars"> {{#testHelper this}} <a href="/{{slug}}">{{title}}</a> {{/testHelper}} </script> <script> Handlebars.registerHelper('testHelper', (ignore, opt) => { var data = [ { slug: 'Test', title: 'This is it!' }, { slug: 'Test 2', title: 'This is the second it!' }, ]; var results = ''; data.forEach((item) => { results += opt.fn(item); }); return results; }); var t = Handlebars.compile($('#t').html()); $('body').append(t({})); </script> </body> </html> 

Let me also echo what others have been trying to tell you. It doesn't make a lot of sense to try to populate data within your templates. This should be passed as context for your templates to act on. Otherwise, you are mixing your business logic with your template logic (view) and this complicates things needlessly.

Here's a simple change you can make in the same snippet, passing the data to your templates:

 <!DOCTYPE html> <html> <head> <title>Page Title</title> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/2.0.0/handlebars.js"></script> </head> <body> <script id="t" type="text/x-handlebars"> {{#testHelper this}} <a href="/{{slug}}">{{title}}</a> {{/testHelper}} </script> <script> Handlebars.registerHelper('testHelper', (ignore, opt) => { var results = ''; data.forEach((item) => { results += opt.fn(item); }); return results; }); var data = [ { slug: 'Test', title: 'This is it!' }, { slug: 'Test 2', title: 'This is the second it!' }, ]; var t = Handlebars.compile($('#t').html()); $('body').append(t(data)); </script> </body> </html> 

This way you can retrieve your data in your javascript and keep the templates for what they were intended - formulating html.

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