Reputation: 1859
I'm trying to write a custom iterator in spacebars (I'm using meteor 1.1.3). The iterator is to be a sequential for loop (basically to replace my usage of #each when needed since I believe #each is not guaranteed to be sequential in its iteration).
I have tried the following:
In lib -
UI.registerHelper 'sequentialFor', () ->
ret = ""
for i in [[email protected]]
id = @[i]
ret = ret + Template.noop
ret
noop.html -
<template name="noop">
{{> UI.contentBlock this}}
<template>
main.html -
{{#sequentialFor ids}}
<div id="wow-{{this}}">stuff</div>
{{/sequentialFor}}
ids in the above is an array of strings passed from one of main's template helpers.
Right now it complains the the return from my UI helper is [object Object] [object Object]. For sanity's sake I know that if I replace my UI helper with:
UI.registerHelper 'sequentialFor', () ->
//ret = ""
//for i in [[email protected]]
// id = @[i]
// ret = ret + template
id = @[0]
Template.noop
I get that the div in my main.html shows up with the appropriate id as a part of its id attribute as desired. However, I can't seem to make the for loop work.
I can't simply return the div in main.html directly from the helper because I have a lot of divs that I need to wrap with my new iterator, each of which has very different attributes.
I guess the simple question is, how do I define my own block iterator (akin to #each) in spacebars?
The more difficult question may be, what is wrong with my approach above?
I have considered a wide array of resources but have only the found the following to be very helpful: How to pass an object from to a block helper back to the block in meteor blaze? https://github.com/meteor/meteor/wiki/Using-Blaze https://github.com/meteor/meteor/blob/devel/packages/spacebars/README.md Iterating over basic “for” loop using Handlebars.js
NOTE I'm using coffeescript
Upvotes: 2
Views: 218
Reputation: 4101
I managed to get a custom iterator using a recursive technique similar to what you might use in Haskell or Lisp:
<body>
{{#countdown n=5}}
<p>item {{this}}</p>
{{/countdown}}
</body>
<template name="countdown">
{{#if positive}}
{{> Template.contentBlock n}}
{{#countdown n=nMinusOne}}
{{> Template.contentBlock this}}
{{/countdown}}
{{/if}}
</template>
Template.countdown.helpers({
positive: function () {return this.n > 0;},
nMinusOne: function () {return this.n - 1;}
});
See meteorpad.
The performance is probably far worse than the usual {{#each}}
.
Upvotes: 1
Reputation: 514
It appears to me that you want to create a <div>
for each of an array of IDs (correct me if I'm wrong). This is how I would go about it, no custom iterator necessary:
Template.registerHelper('ids', function(arrayWithIds) {
if (!arrayWithIds) return [];
// do some sorting or whatever with arrayWithIds, for example:
var arrayOfIds = _.map(arrayWithIds, function(obj) {
return obj._id;
});
return arrayOfIds;
});
Then in main.html:
{{#each ids someDataSetWithIds}}
// `someDataSetWithIds` is the helper's parameter
// `this` in each case is an ID
<div id="wow-{{this}}"></div>
{{/each}}
If your helper returns an object, you would use this._id
in the template, instead. Did I misunderstand what you're trying to achieve?
Upvotes: 0