Search code examples
javascripturlhashhandlebars.js

Change expression based on url hash - handlebars.js


I have just started using handlebars and you can't use Js with the templates so you have to use a helpers(?) or so I have lead myself to believe.

I want to change my expression based on URL hash.

so if my URL was www.mysite.com/template.html#new I'd want #each to be {{#each New}} and if it was /template.html#anythingelse I'd want it to change to {{#each anythingelse}}

I know I can get the hash with var hash = window.location.hash; and normally use it with +hash+ but with handlebars I can't well not as far as I know?

and I understand the may not be good as the user can enter #anythingtheywant but it won't matter in the way i am using it.

    <ul>
        {{#each New}}
         {{#each genres}}

            <li>{{genre-name}}
                <ul style="list-style-type:none"> 
                    {{#each list}}
                        <li>{{name}}</li>
                    {{/each}}
                </ul> 
            </li>
        {{/each}}
        {{/each}}
    </ul>
  {{/each}}

Any help or insight would be amazing.


Solution

  • As usual, there are several ways to do this.

    I think an own written block helper is a must here. Let us name it customEach. Further on let templateName be our template's name. For this solution we have to make sure that all our arrays are passed to Handlebars. In the author's example this would be an array called new and one called anythingelse.

    Thus the Handlebars call would be something like:

    var ctx = { 
        new: new, 
        anythingelse: anythingelse 
    };
    
    Handlebars.templates["templateName"](ctx);
    

    The custom block helper 'customEach' could something like the following:

    Handlebars.registerHelper('customEach', function(options) {
        var hash = window.location.hash.substr(1);
    
        return options.fn(this[hash]);
    });
    

    Note that within a helper (that's simply some JS code) one does have access to the URL's hash component.

    The options parameter that is passed to our helper by the Handlebars plugin contains a function named fn. It behaves as a normal compiled template. So just pass the wanted array to it (this holds the current context which corresponds to our ctx variable we've passed to Handlebars earlier). In other words fn just processes the stuff that is defined between {{#customEach}} and {{/customEach}}.

    The new template would be:

    <ul>
        {{#customEach}}
            {{#each genres}}
                <li>{{genre-name}}
                    <ul style="list-style-type:none"> 
                        {{#each list}}
                            <li>{{name}}</li>
                        {{/each}}
                    </ul> 
                </li>
            {{/each}}
        {{/customEach}}
    </ul>
    

    Of course one should implement some error handling here, e.g. if a specific hash value #anythingtheywant isn't defined in our original context.

    I haven't tested my code, yet. But even if it fails I hope the idea behind it is clear.