looping data structures with mustache

3,923 views
Skip to first unread message

trevor...@gmail.com

unread,
Jan 19, 2011, 5:36:10 PM1/19/11
to sca...@googlegroups.com
What type of data structures does mustache support?  I tried looping a java Map<Integer, MyCustomObject> but it's just calling toString() on it instead of iterating.

James Strachan

unread,
Jan 20, 2011, 5:57:55 AM1/20/11
to sca...@googlegroups.com

So we try to support all the common stuff you'll wanna do; navigating
across objects, functions, collections, Map, Option, NodeSeq,
PartialFunction, Traversable etc. If ever you want to look at the
detail of how the navigation of scopes work in Mustache, all the magic
is here:
https://github.com/scalate/scalate/blob/master/scalate-core/src/main/scala/org/fusesource/scalate/mustache/Scope.scala#L40

Though I noticed from your mail that we don't currently support the
java.util.Collection/Map types, so I've raised this issue
http://www.assembla.com/spaces/scalate/support/tickets/199

However one thing with Mustache and a Map is there's no way to
determine if you mean 'iterating' and not 'navigating' since Mustache
has no logic in the templates; just sections which apply to both.

For a Collection/List there really is only iterating, so when you
create a section which is-a Collection, its clear what to do.

Right now when you create a section which is-a Map then the default
Mustache way is to treat the Map as a kinda Object where named values
inside the section refer to entries in the Map.

e.g. see this test case...
https://github.com/scalate/scalate/blob/master/scalate-core/src/test/scala/org/fusesource/scalate/mustache/MustacheTest.scala#L43

the {{#person}} section resolves to a Map which then resolves {{name}}
using a lookup.

There's no canonical way I know of in Mustache to say 'iterate the
map'. Typically the Mustache way is to hide all this stuff by creating
your context correctly so the names you use in your template are
mapped to the right kinds of objects - so that if you want a Map to
look like a Collection, then don't put a Map in there, put a
Collection :)

So one way around this is just to fix your context so rather than
putting a Map in there you put in map.entrySet() in Java) or
map.iterator in Scala.

It can be a bit painful messing around with your context adding these
different views into your model (though this is the trade off really
between Mustache and SSP/Scaml/Jade - the Mustache way is to defer all
complexity into the context creation, leaving the template navigating
simple names).

Maybe we could implement a special name like "iterator" that if it is
not a key in the Map, it returns the iterator over a Map?

e.g.

{{#person}}
// look up a key in the map here if required

// now lets iterate through all keys
{{#iterator}}
{{key}} = {{value}}
{{/iterator}}
{{/person}}

Though this isn't really the Mustache way, but it might be a useful extension?

--
James
-------
FuseSource
Email: ja...@fusesource.com
Web: http://fusesource.com
Twitter: jstrachan
Blog: http://macstrac.blogspot.com/

Open Source Integration

trevor...@gmail.com

unread,
Jan 20, 2011, 12:59:15 PM1/20/11
to sca...@googlegroups.com
Thanks for the thorough reply!

We're specifically trying to keep our mustache templates compatible with mustache.js, so we decided to build simpler models :)

The {{#iterator}}{{/iterator}} idea seems pretty intuitive though. I could see that being very useful in a case where you didn't care about compatibility with other mustache implementations.

Trevor

James Strachan

unread,
Jan 20, 2011, 1:37:15 PM1/20/11
to sca...@googlegroups.com

I guess even in JS you could add an iterator() function to all Objects
to iterate over all key/value pairs

Reply all
Reply to author
Forward
0 new messages