8

I'm attempting to implement the Todo-example given in the Spine.js docs, given here: http://spinejs.com/docs/example_tasks

only I'd like to use Handlebars instead of jQuery.tmpl. I'm using Handlebars 1.0.rc.1

However, when I attempt to call:

template: Handlebars.compile($('#history-template').html()),

render: function(){
    var t = this.template(this.item);
    this.replace(t);
    return this;
}

Handlebars throws an exception at this.template(this.item):

Uncaught TypeError: Cannot call method 'match' of undefined

In the Handlebars lexer, this._input is coming back as undefined.

My template is as follows:

<script id='history-template' type='text/x-handlebars-template'>
    <div class="content-inner {{#if viewed}}msg_unseen{{/if}}">                                             
        <div>{{data}}</div>
    </div>
</script>

Data:

"[{"data":"hello","id":"c-0"}]"

Any ideas?

amhou
  • 101
  • 3
  • Typo in above description, should be selecting by #history-template. But unfortunately still does not work with the given data model, which is how Spine appears to handle its JSON. – amhou Dec 03 '12 at 19:27

2 Answers2

1

The problem appears to be:

  1. a mismatch in the IDs -- your template ID is history-template, but you're trying to select it as $("#my-template).
  2. Your data should be written like {"data":"hello","id":"c-0"} (an object), without the square brackets (which make it an array).

I can run your code once I make those two corrections. See here for a working demo.

var data = { data: "hello", id: "c-0" };
var template = Handlebars.compile($('#history-template').html());
var html = template(data);

(See also here for a confirmation that the #if logic is working correctly.)


Edit

To use the data in the array form -- { data: "hello", id: "c-0" } -- as far as I can tell, in order to use it in a Handlebars template, you need to wrap it in an object:

var obj = { data: "hello", id: "c-0" };
var handlebarsData = { items: obj };

That way you can use the Handlebars iteration form {{#each items}}:

{{#each items}}
    <div class="content-inner {{#if viewed}}msg_unseen{{/if}}">                                             
        <div>{{data}}</div>
    </div>
{{/each}}

Here's the updated Fiddle.

McGarnagle
  • 101,349
  • 31
  • 229
  • 260
  • 1) I typo a word. When selecting by #history-template, it still doesn't work using the given data model. 2) Spine.js appears to hold its JSON in that format, I'd rather use the same model? – amhou Dec 03 '12 at 19:28
  • @user1868231 did you see my suggestion to change the data object? In your question, you've written it as an array, but your template is looking for an object. – McGarnagle Dec 03 '12 at 19:32
  • I did, but as I said above, Spine.js holds its data in an array of hashes. I'd rather use what Spine has provided. – amhou Dec 04 '12 at 00:04
  • @amhou gotcha ... please see my update above. If you tweak the Handlebars template, and wrap the data in an object, then it should work. – McGarnagle Dec 04 '12 at 00:14
0

You are passing in the data incorrectly.

According to the offical handlebars documentation the data is suppoused to be passed to handlebars as an object. For example:

{"foo":"bar","baz":"faz"}

With a template of:

<div>{{foo}}</div>
<div>{{baz}}</div>

will be rendered as

<div>bar</div>
<div>faz</div>
0xcaff
  • 13,085
  • 5
  • 47
  • 55