Handlebars.js: Parse error with each helper: Expecting "ID", got undefined

Created on 29 Jun 2012  ·  6Comments  ·  Source: handlebars-lang/handlebars.js

I get the following error trying the example in the docs:

Uncaught Error: Parse error on line 3:
{{ #each people }} -------^
Expecting 'ID', got 'undefined'

feature

Most helpful comment

OK, the issue is pretty simple actually, not related to non-printing chars, but my server side templating engine put a space before }}.
The following solves the issue, though I am not sure whether handlebars should be fixed to parse {# each people }} correctly.

      source = $("#people-in-clients-template").html();
      source = source.replace(/ }}/g, "}}");
      source = source.replace(/{{ /g, "{{");

All 6 comments

@ustun, You'll need to show us a bit more code before we can really properly debug this. It would be most helpful if you could put together a jsfiddle for this.

@wagenet Thanks for the fast response. The problem is, I can't even demonstrate it, as it is the same as the simple #each example on the main page. If I try it in jsfiddle, or even on the Chrome console, inputting the text, it works, but for some reason, the text returned by html() fails. I'm wondering if it is somehow getting confused by newlines.

Here is the console session. As you can see, if I enter the template manually, it works.

template = $("#people-in-clients-template").html()
"

{{ #each people }}
<li>{{ this }}</li>
{{ /each }}

"
t = Handlebars.compile(template);
function (context, options) {
    if (!compiled) {
      compiled = compile();
    }
    return compiled.call(this, context, options);
  }
t({"people": ['foo','bar']})
Error: Parse error on line 3: {{ #each people }}<li> ---^ Expecting 'ID', got 'undefined'

Now trying manually:

template = "{{#each people }}<li>{{ this}}</li>{{/each}}"
"{{#each people }}<li>{{ this}}</li>{{/each}}"
t = Handlebars.compile(template);
function (context, options) {
    if (!compiled) {
      compiled = compile();
    }
    return compiled.call(this, context, options);
  }
t({"people": ['foo','bar']})
"<li>foo</li><li>bar</li>"

Trimming the html() output has no effect either.

So,

  template = $.trim($("#people-in-clients-template").html())
"

{{ #each people }}
<li>{{ this }}</li>
{{ /each }}

"
t = Handlebars.compile(template);
function (context, options) {
    if (!compiled) {
      compiled = compile();
    }
    return compiled.call(this, context, options);
  }
t({"people": ['foo','bar']})
Error: Parse error on line 3: {{ #each people }}<li> ---^ Expecting 'ID', got 'undefined'

It seems like there is some binary data in my template:

    template = "{{#each people }}<li>{{ this}}</li>{{/each}}"
"{{#each people }}<li>{{ this}}</li>{{/each}}"
/[\x00-\x1F]/.test(template)
false
template = $("#people-in-clients-template").html()
"

{{ #each people }}
<li>{{ this }}</li>
{{ /each }}

"
/[\x00-\x1F]/.test(template)
true

This is the charcodes of the problematic template:

a = [10, 10, 123, 123, 32, 35, 101, 97, 99, 104, 32, 112, 101, 111, 112, 108, 101, 32, 125, 125, 10, 123, 123, 32, 116, 104, 105, 115, 32, 125, 125, 10, 123, 123, 32, 47, 101, 97, 99, 104, 32, 125, 125, 10, 10]

b="";

for (i = 0; i < a.length; i++) {
b += String.fromCharCode(a[i]);
}

t = template({"people: ['foo','bar']});

Here is the jsfiddle:

http://jsfiddle.net/8nugY/

OK, the issue is pretty simple actually, not related to non-printing chars, but my server side templating engine put a space before }}.
The following solves the issue, though I am not sure whether handlebars should be fixed to parse {# each people }} correctly.

      source = $("#people-in-clients-template").html();
      source = source.replace(/ }}/g, "}}");
      source = source.replace(/{{ /g, "{{");

Seems like bad encoding vs an actual bug.

Was this page helpful?
0 / 5 - 0 ratings