3

In my .hbs delivered by my node server:

<script src="/javascripts/handlebars.min-latest.js"></script>

<script id="entry-template" type="text/x-handlebars-template">
  <div class="entry">
    <h3>{{title}}</h3>
    <div class="body">
      {{body}}
    </div>
  </div>
</script>

In my client-side javascript file:

var source   = $("#entry-template").html();
var template = Handlebars.compile(source);
var context = {title: "My New Post", body: "This is my first post!"};
var html    = template(context);
console.log(html);

My output:

<div class="entry">
    <h3></h3>
    <div class="body">

    </div>
</div>

Basically, even with the simplest example on their frontpage, it isn't working. Is it because I'm using handlebars on the front and back end? If so, how can I go around that?

db2791
  • 1,040
  • 6
  • 17
  • 30

4 Answers4

4

If you use Handlebars for both backend and frontend there is an easy fix. Just escape the variables which are meant for your frontend parser by adding a \ in foront of them like so \{{myVar}}, and leave the variables which are to be parsed by the server to {{myServerVar}}.

<script type="text/x-handlebars-template" id="my-row-template"> ​
    <tr>
        <td></td>
        <td>\{{fieldName}}</td>
    </tr>
</script>
1

Client-side templates when using Handlebars on the server

If you’re using Handlebars on the client and the server, you’ll run into this issue where the client-side templates will be parsed by the view engine on the server. For example, you may have a file like this:

 <h1>My Page Title</h1>
 <!-- This template should be transformed into HTML by the server -->
 <div id="photoList" class="pure-g">
    {{#each photos}}
        <div class="photo pure-u-1-12" data-photo-id="{{id}}">
            <img class="pure-u-1" src="{{src}}">
        </div>
    {{/each}}
 </div>

<!-- This template should not be touched. It's for the client -->
 <script type="text/x-handlebars" id="lightbox-template">
    <img class="lightbox-image" src="{{large}}">
    <div class="lightbox-meta">
        <a class="pure-button lightbox-link" href="{{url}}">View on Flickr</a>
        <button class="pure-button lightbox-link lightbox-hide">Hide</button>
    </div>
 </script>

When you view this on the browser, the tags ({{..}}) within will be parsed out. You’ll get something like this, which is useless:

<!-- I can't use this template on the client anymore!! -->
<script type="text/x-handlebars" id="lightbox-template">
  <img class="lightbox-image" src="">
<div class="lightbox-meta">
    <a class="pure-button lightbox-link" href="">View on Flickr</a>
    <button class="pure-button lightbox-link lightbox-hide">Hide</button>
 </div>
</script>

Fortunately, the fix for this is very simple, albeit not documented anywhere. Just add a \ in front of all the opening tags ({{). The \ will be parsed out during the compilation step, and you’ll have a perfectly usable template on the client.

<!-- Add a \ before the handlebars -->
<script type="text/x-handlebars" id="lightbox-template">
  <img class="lightbox-image" src="\{{large}}">
  <div class="lightbox-meta">
     <a class="pure-button lightbox-link" href="\{{url}}">View on Flickr</a>
     <button class="pure-button lightbox-link lightbox-hide">Hide</button>
  </div>
</script>

Source: link

Medi
  • 1,026
  • 2
  • 9
  • 12
1

searching for issues when trying to use handlebars with shopify themes?

You are definitely experiencing liquid parsing the variables and serving empty strings to the client. The liquid solution is to enclose your handlebar template within raw & endraw tags.

{% raw %}
<script id="cartItemTemplate" type="text/x-handlebars-template">
   ...
</script>
{% endraw %}
eballeste
  • 712
  • 1
  • 11
  • 23
0

Add $('body').append(html); to you script:

var source   = $("#entry-template").html();
var template = Handlebars.compile(source);
var context = {title: "My New Post", body: "This is my first post!"};
var html    = template(context);

$('body').append(html);

Fiddle Demo

Nikolay Ermakov
  • 5,031
  • 2
  • 11
  • 18
  • It works on Jsfiddle, but not on my site. Also, my issue is not just not seeing the text on my screen. The template doesn't register the context at all, as can be seen when I try to log it. – db2791 Oct 21 '16 at 01:37
  • How are you loading your client-side javascript file? Are you sure it comes on dom ready or in the page bottom? Do you have any errors in console? – Nikolay Ermakov Oct 21 '16 at 01:40
  • I am not getting any errors in the console, only the text that I have provided in the third snippet of the question – db2791 Oct 21 '16 at 01:44
  • What about loading your client-side script? Are you sure it comes on dom ready or in the page bottom - when all the rest has loaded? – Nikolay Ermakov Oct 21 '16 at 01:46
  • Yes it comes after DOM is loaded, I could also tell because `var source = $("#entry-template").html();` does not give an error. The HTML is found, but is not rendered. – db2791 Oct 21 '16 at 01:49
  • The solution should be very simple I believe. However I have no other ideas except can you post your whole resulting page in the question. – Nikolay Ermakov Oct 21 '16 at 01:51
  • 1
    I realized the problem. The server-side handlebars is interfering with client-side handlebars. All the {{}} tags that are meant for the client-side are being annulled by the server-side templating. Right now, the only solution I can see is using a different templating engine on the front-end. – db2791 Oct 21 '16 at 16:00
  • 2
    Glad you figured that out. Maybe there are still some solutions to have it both ways - http://stackoverflow.com/questions/10037936/node-js-with-handlebars-js-on-server-and-client – Nikolay Ermakov Oct 21 '16 at 17:40
  • Thanx for sharing that question! I ran into the same problem and was also thinking that server side hbs blocks itself somehow on front-end. Changing template engine from hbs to ejs fixed my problem! Thank you! – JSEvgeny Jan 30 '17 at 12:51