alexdmejias
alexdmejias

Reputation: 1429

handlebars partial context

I have an array that contains the information for social buttons (href,alt,img). I created a partial that would cycle through the array and add the objects, here is what I have.

the array:

var social=[
    {

        "url":"http://twitter.com/share?text="+encodeURIComponent(this.title)+" "+encodeURIComponent('#grnsrve')+"&url="+domain+"&via="+twitterAcct,
        "image":"IMG/media/twitter_16.png",
        "alt":"twitter link"
    },
    {
        "url":"http://twitter.com/share?text="+encodeURIComponent(this.title)+" "+encodeURIComponent('#grnsrve')+"&url="+domain+"&via="+twitterAcct,
        "image":"IMG/media/twitter_16.png",
        "alt":"twitter link"
    },
    {
        "url":"http://twitter.com/share?text="+encodeURIComponent(this.title)+" "+encodeURIComponent('#grnsrve')+"&url="+domain+"&via="+twitterAcct,
        "image":"IMG/media/twitter_16.png",
        "alt":"twitter link"
    }
];

The template:

social_partial = '<a href="{{url}}" alt="{{alt}}"><img src="{{image}}"/></a>';

The partial function:

Handlebars.registerPartial('addSocial',social_partial);

and the main template:

<div class="tip_social">
    {{>addSocial social}}
</div>

I'm getting a 'Depth0 is undefined error'. I tried looking for documentation on parials getting a different context , but I have yet to find it.

edit here is a more complete fiddle of it

Upvotes: 3

Views: 15912

Answers (3)

isacookie
isacookie

Reputation: 1

Here is the only way I found: Handlebars doc indicates that you need to use Block Helpers to pass different contexts. So here are two files: the main template and the script in node contening two contexts: the main context and the context for the social data. The script having the source for the partial template. The Block is #twitter_list and its associated registerHelper uses option.fn(other_context_object) which seems the only way to pass another context in handlebars.

Main template:

<html>
<head>
<title>Test content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
    <div id = main>
        <!-- This is using the main context-->
        <h2> Hello {{name}}!</h2>
        <p>{{some_content}}</p>


        <!-- This is using the partial template and its own context -->
        <ul>
        {{#twitter_list}}
            {{>yourpartial}}
        {{/twitter_list}}
        </ul>

    </div>  

</body>
</html>

The javascript using Node js:

var handlebars = require('handlebars'),
fs = require('fs');

const main_context = { name: "world",
                        some_content: "Bla bla bla all my bla bla"};

const twitter_data={social:[
    {
        "url":"some url 1",
        "image":"IMG/media/twitter_1.png",
        "alt":"twitter link 1"
    },
    {
        "url":"some url 2",
        "image":"IMG/media/twitter_2.png",
        "alt":"twitter link 2"
    },
    {
        "url":"some url 3",
        "image":"IMG/media/twitter_3.png",
        "alt":"twitter link 3"
    }
]};


var partial_source = '{{#each social}}<li><a href="{{url}}" alt="{{alt}}"><img src="{{image}}"/></a></li>{{/each}}';

handlebars.registerPartial('yourpartial', partial_source);

handlebars.registerHelper('twitter_list', function(options) {
    //you need to use the options.fn to pass the specific context
    return options.fn(twitter_data);
});

fs.readFile('maintemplate1.hbs', 'utf-8', function(error, source){
  var template = handlebars.compile(source);
  var html = template(main_context);
  console.log(html)
});

Upvotes: 0

Paul
Paul

Reputation: 1138

Same issue for me. Bit of digging and one face-palm later here's what I've found.

tl;dr answer

Be very careful about the context you pass to your partial. If you somehow pass a null, or empty object to your partial you'll get the depth0 is undefined error

Very slightly longer answer

JSFiddle Examples:

The only thing that changed in the working version is I'm passing a valid context to the partial.

BTW a very helpful trick is to use the debug helper from this blog

Answerbot dictator "code example"

<script id="parent">
 <table>
   <thead>
      <tr>
        <th>One</th>
        <th>Two</th>
      </tr>
    </thead>
    <tbody>
    {{#each collection}}
       {{>myPartial nothingHere}} <!-- Broken context -->
    {{/each}}
    </tbody>
 </table>
</script>

The broken context above will cause handlebars to die. For your problem try digging into that with a {{debug}} tag and see if that helps.

For a better code example please just take a look at the jsFiddles. Reposting all the code in here, formatting it to make it pretty looking and making the StackOverflow answerbot dictator happy was a bit much for doing this at work ^_~

Upvotes: 8

mu is too short
mu is too short

Reputation: 434945

I'm not sure what you're doing wrong as you haven't provided enough code to duplicate your problem. However, it isn't hard to make it work. First of all, your main template should be iterating over social and feeding each element to your partial, something like this:

<script id="t" type="text/x-handlebars-template">
    {{#each social}}
        <div class="tip_social">
            {{>addSocial this}}
        </div>
    {{/each}}
</script>

And then you can get your HTML with something like this:

​var t    = Handlebars.compile($('#t').html());
var html = t({social: social}));​​

Demo: http://jsfiddle.net/ambiguous/SsdbU/1/

Upvotes: 2

Related Questions