Handlebars version update #489

Closed
sdossick opened this Issue Nov 18, 2012 · 70 comments

Comments

Projects
None yet

It's a drop hard to tell what version of Handlebars the current templating system is based on. More recent versions of Handlebars support nice-to-have things like an @index context-dependent accessor so you can tag the index number of elements of an array you're {{each}}-ing through.

An update to the latest RC of handlebars would be great, as would some docs on how to Spark-ify our own versions of handlebars or other templating systems.

Member

gschmidt commented Nov 29, 2012

@sdossick, thanks for this. You're asking for three things here, all of which we should do:

  1. Better document the version of Handlebars that Meteor supports
  2. Extend Meteor's Handlebars implementation with the new features (@index sure does sound nice)
  3. Make templating system implementations fully pluggable (it's close but not quite there yet -- I suppose we need something like a 'language' attribute on tag, or determine it from the file extension?), and write a walkthrough on Spark-ifying your favorite templating system

    I expect that we (the core team) will do them in roughly this order, but it may be a while before we get to all of them because we're pretty swamped right now.

    We would happily take pull requests on (2). The only thing that Meteor uses from the official Handlebars distribution is the parser (we ship the templates to the client as an AST rather than complied code), so it's not as simple as pulling the latest upstream version of Handlebars, but I'd expect it to be fairly self-contained.

cscott commented Dec 11, 2012

One odd thing is that it's surprisingly difficult to pretty-print a comma-separated list in Meteor/handlebars. @index would probably help this, because you could do:

    {{each collection}}
       {{if @index 0}}, {{/if}}
       {{some_field}}
    {{/each}}

which is a reasonable, if clunky, way to do such a simple task.

Owner

glasser commented Dec 11, 2012

We would want to make sure that @index is appropriately reactive; normally
Meteor can react to the ordering of a list changing without the data
changing just by moving around DOM nodes without re-rendering, so we'll
want to make sure that we re-render if the list nodes depend on @index.

cscott commented Dec 12, 2012

Exactly -- that's why the simple "display a comma-separated list" task is so annoying currently -- you have to manage all those dependencies yourself. If @index is implemented "properly", then that's all done automagically.

(fwiw, i'm using CSS to add the commas between elements myself; ::after and :last-node are much easier than doing this properly with templates!)

I have been creating helpers for common tasks. Seems like this is also a fine solution for things you do a lot rather than some hacky code all over the place.

I did JSP for a long time and this is very common in the JSP world.

Example:

Handlebars.registerHelper('calendar', function (v) {
    return moment(v).calendar().replace('last ','');
});

In the template:

{{calendar someDate}}

You could easily do the same for lists, something like:

Handlebars.registerHelper('commaList', function(list) {return list.join(',')}

cscott commented Dec 12, 2012

@scottburch i'm pretty sure that doesn't actually work, due to the way meteor handles recursive template invocations. ie, I don't want to give the helper a list of strings, i want to use {{#each}} to generate document fragments from each instance of my collection, and then combine those.

See issue #499 for more details on the awkwardness.

You can work with collections in the helpers. I do it frequently. FYI. I do use recursive templates in a tree structure and I did have to do some trickery to get it to work, but it can. Maybe my example was bad, I was trying to duplicate your example.

cscott commented Dec 12, 2012

yes, i know you can do it. my meta-point was just that "it's more
painful than it ought to be", and by requiring custom helper functions
starts blurring the distinction between presentation and code. The
meta-meta-point is that a minimal template library like handlebars doesn't
have very many features, but the ones it does have are there for a reason,
and so i'm +1'ing the OP's request for a handlebars update.

Sounds good. I don't see it the same way since view helpers are still part of presentation and have nothing to do with "code". Just a point of view.

One more note that might help. My meteor app has more layers than the examples show. I have the html files and controllers. My controllers are still part of presentation because the real work is done in the model layer. That makes testing easier since I don't do testing in my controller layer. The controllers simply have view helpers and trap events. They then delegate any real work to the model layer.

This is more how Java style apps are designed.

Would be really nice to see @index work.

neekey commented Mar 9, 2013

+1

Owner

glasser commented Mar 12, 2013

OK, so a challenge in implementing @index is making sure that it does the right thing with reactivity. Specifically, right now when you remove an element from a list or add one or move elements around, the DOM nodes for the other elements of the list are not re-rendered, just the relevant ones. (That's what Spark.list does.) If the DOM nodes depend on @index though, we'd have to re-render everything.

One possibility for implementing this: we detect for a given {{#each}} if its @index is actually used (deep icky Handlebars hooks...) and if so, we don't use Spark.list at all (ie, we just do the standard each over cursor.fetch).

profikid commented May 5, 2013

+1

+1
I'd definitely be thankful for @index, @FIRST, @last, @odd, @even and the like.

jonjamz commented Jun 5, 2013

+1

owenrh commented Jun 21, 2013

+1, seems like a must for me. Need to be able to easily check odd, even, index, etc. Has anyone got a work round for this?

Xyand commented Jun 24, 2013

+1

+1

sokki commented Jun 25, 2013

+1

Contributor

michaelbishop commented Jun 26, 2013

+1

Collaborator

mitar commented Jul 3, 2013

+1 Not to mention that handlebars is now 1.0. So Meteor should at least support everything version 1.0 of handlebars provides. Otherwise is really hard to know which documentation to read.

Owner

glasser commented Jul 10, 2013

The internal implementation of how Meteor processes templates is being rewritten on the shark branch. Adding features to the currently released implementation is unlikely to be a good use of time. Stay tuned :)

+1

The latest version of handlebars also supports using #each to iterate over an object and provides @key to print out the keys - adding this in would really help!

@raix raix referenced this issue in CollectionFS/Meteor-CollectionFS Jul 25, 2013

Closed

Uncaught TypeError: Object #<Object> has no method 'userId' #60

kkm commented Jul 26, 2013

+1

mxab commented Aug 3, 2013

+1

dohomi commented Aug 5, 2013

+1

+1

+1

zivel commented Aug 30, 2013

+1

+1

@ghost

ghost commented Sep 10, 2013

Code Bounty

+1

Tenari commented Sep 24, 2013

+1

+1

+1

For anyone struggling with this issue, you might want to consider using the Template rendered() callback, and then calculating the index in place.

Template.my_template.rendered = function() {
  $('.some-selector').each(function(index) {
    this.setAttribute('data-slide-to', index);
  });
};

arunoda commented Oct 28, 2013

Check this for a workaround for getting the index (or key)

Not speaking against the work requested, but you can achieve csv perhaps more simply by having two helper data sources, first and remaining. Remaining is an each with a preceding comma.

first returns array.shift().

oyvinmar pushed a commit to oyvinmar/programming-ladder that referenced this issue Nov 5, 2013

mobweb commented Nov 10, 2013

+1

Contributor

DenisGorbachev commented Nov 13, 2013

+1

+1

zeopix commented Nov 18, 2013

+1
this is a very important issue... this version even not supports @index on "each" statements....

Lepozepo commented Dec 9, 2013

+1

Collaborator

mitar commented Dec 10, 2013

I think this is getting in as a part of Meteor UI. Try it out.

Collaborator

mitar commented Dec 10, 2013

(And probably open tickets against it, if something is missing.)

Owner

glasser commented Dec 11, 2013

Yes, our plan is that instead of continuing to use a heavily modified and incompatible old version of Handlebars, we are admitting that Meteor template language is not the same as Handlebars, and giving it a new name and implementation (currently planning on calling it "Spacebars", though that may change). (Just like Handlebars itself was forked from Moustache.) We don't plan to upgrade to a new version of Handlebars per se, but to add features (like @index) directly to Spacebars.

See https://github.com/meteor/meteor/blob/shark/packages/spacebars/syntax.md for the current Spacebars documentation.

@glasser glasser closed this Dec 11, 2013

The link you just posted @glasser is broken: https://github.com/meteor/meteor/blob/shark/packages/spacebars/syntax.md

There is no syntax.md file in that repository.

Contributor

emgee3 commented Dec 21, 2013

Pretty sure it was there and has since been refactored into a different folder. New link: https://github.com/meteor/meteor/blob/shark/packages/spacebars-compiler/syntax.md

kevb commented Apr 15, 2014

Anyone got an updated link, it's broken?

I'm still lost as to whether this is now possible with Spacebars...

kevb commented Apr 16, 2014

Ah thanks. So it seems that an @index accessor in a #each iteration is still not available?

Owner

glasser commented Apr 17, 2014

Correct.

vflyson commented May 26, 2014

My code to get the {{index}} thingy within the {{#each}} loop:

Template.index.helpers({
  langs: function() {
    var langs = LANGS.find({}, {limit: PP, skip: (Session.get('lang_page')-1)*PP}).fetch();

    if( LANGS.find().count() > PP )
      langs.push({_id: 'more', name: Session.get('lang_page')+'/'+Math.ceil(LANGS.find().count() / PP)})

    var index = 0;
    langs.map(function(o, i) {
      langs[i].index = index++;
    })

    return langs;
  }
});

jonjamz commented May 26, 2014

I've done something similar to @flatr0ze and it works fine.

still no @index support :(
+1

Collaborator

mitar commented Feb 17, 2015

It is coming in #3560.

+1

+1

Collaborator

laosb commented Jun 27, 2015

Could I say that you are mentioning the organization index on GitHub by mistake? Please use @index to prevent from mentioning an organization.

Is there an ETA when the @index might be supported?

kkm commented Sep 17, 2015

harmless index for handlebars took for 3 years.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment