3gwebtrain
3gwebtrain

Reputation: 15303

How to add custom class names to elements in a Handlebars template using a helper function?

I have a sample object with which I am trying to make a navigation bar, with each li to have a custom class name like this:

<ul>
      <li class="mainLink1">
          <a href="m1/home.html">home</a>
          <ul class="subParent1">
              <li class="sublink1"><a href="s1/home.html">s1/home</a></li>
              <li class="sublink2"><a href="s2/home.html">s2/home</a></li>
         </ul>
     </li>
     <li class="mainLink2">
         <a href="m2/service.html">service</a>
         <ul class="subParent2">
             <li class="sublink1"><a href="s1/service.html">s1/service</a></li>
             <li class="sublink2"><a href="s2/service.html">s2/service</a></li>
        </ul>
     </li>
</ul>

I know that all these class names have to be generated by a helper function, but I'm confused because I could not get proper results. Here is my try.

My html with template:

<div id="navigate"></div>

<script type="text/handlebars-x-template" id="menu">
    <ul>
        {{#list}}
           <li><a href="{{link}}">{{name}}</a></li>
            {{#if list.sub}}
                <ul>
                    {{#each this}}
                       <li><a href="{{link}}">{{name}}</a></li>
                    {{/each}}
                </ul>
            {{/if}}
        {{/list}}
    </ul>
</script>

My helper function and implementation:

var obj = [{"name":"home","link":"m1/home.html","sub":[{"sname":"s1/home","slink":"s1/home.html"},{"sname":"s/home","slink2":"s2/home.html"}]},{"name":"service","link":"m2/service.html","sub":[{"sname":"s1/service","slink":"s1/service.html"},{"sname":"s/service","slink2":"s2/service.html"}]}]

Handlebars.registerHelper("list", function(context, option){
    console.log(context, option);
})

var temp = Handlebars.compile($("#menu").html());
var html = $("#navigate").html(temp(obj)); 

I agree that my try is very bad. Any help to correct it and make to apply the class names using @index property.

A fiddle for the above.

Upvotes: 2

Views: 6207

Answers (1)

Sushanth --
Sushanth --

Reputation: 55750

First your custom helper has no context , this is nothing but the context object that is passed in with the name of the helper

Handlebars.registerHelper("list", function(context, option) {

So by default context argument will be options

Context is the one that is passed to the helper

 {{#list this}}
          ^------ This is the context

Next your object is an Array of objects, so your approach will not work. You would require to either change the way you are using the template structure, or iterate over the object and pass in a single object to your template..

And there is no key called list that holds the sub property

{{#if list.sub}}

Supposed to be

{{#if this.sub}}

Code

Handlebars.registerHelper("list", function(context, options) {
    // Return fn from options that will pass in the object to
    // the truthy function
    console.log(context + ' :: ' + options); 
    return options.fn(this);
})

// Compile your template
var temp = Handlebars.compile($("#menu").html());
var $ul = $('#navigate > ul');
// Append it to the container after iterating over array of objects
for(var i=0; i<obj.length; i++) {
    $ul.append(temp(obj[i]));
}

Check Fiddle

UPDATE

Then in that case you would not require the template helper in the first place. Just use the each loop and @index to iterate over the lists.

Template

<script type="text/handlebars-x-template" id="menu">
    {{#each this}}
        <li class="mainLink{{@index}}">
            <a href="{{link}}">{{name}}</a>
        {{#if this.sub}}
            <ul class="subParent{{@index}}">
                {{#each this.sub}}
                    <li class="sublink{{@index}}"><a href="{{slink}}">{{sname}}</a></li>
                {{/each}}
            </ul>
        {{/if}}
      </li>
    {{/each}}
</script>

Check Fiddle

Upvotes: 2

Related Questions