groue / GRMustache

Flexible and production-ready Mustache templates for MacOS Cocoa and iOS
http://mustache.github.com/
MIT License
1.44k stars 190 forks source link

Render index in loop #14

Closed jasperblues closed 12 years ago

jasperblues commented 12 years ago

Comrades, Mustachos!

I'm looking for an easy way to render the item index in a collection, without setting a property on all the fields. Like so:

                    {{#methods}}
                    <string key="NS.key.0">do{{name}}</string>
                    <string key="NS.object.{{index}}">id</string>
                    {{/methods}}

So, for index, I want the number 0, 1, 2, 3, etc. Is there a way to do that?

groue commented 12 years ago

You mean, something like that ?

// template
NSString *templateString = @"{{#GRArrayIndex}}{{#items}}{{index}}:{{description}} {{/items}}{{/GRArrayIndex}}";
GRMustacheTemplate *template = [GRMustacheTemplate templateFromString:templateString error:NULL];

// items
NSArray *items = [NSArray arrayWithObjects:@"foo", @"bar", nil];

// helper for {{index}}
GRArrayIndexHelper *helper = [GRArrayIndexHelper helperWithIndexKey:@"index"];

// render 0:foo 1:bar
NSString *result = [template renderObject:[NSDictionary dictionaryWithObjectsAndKeys:
                                           helper, @"GRArrayIndex",
                                           items, @"items", nil]];
NSLog(@"%@", result);
groue commented 12 years ago

I guess it's exactly what you want.

Actually, the Mustache language itself has no support for array indices.

That's why we need a helper object, and a dedicated section for attaching it (the ugly {{#GRArrayIndex}} in the code above). You can name this extra section the way you want. It's just a matter of attaching the helper to some template section, in which all arrays get indices.

GRArrayIndexHelper.h and GRArrayIndexHelper.m sources are at https://gist.github.com/1966553

Hope it will help, you lazy Mustachos :-)

groue commented 12 years ago

Thanks! You had me find a limitation to the number and date formatting helpers that ship with GRMustache.

Read the "Scope" section of the number formatting guide, because the same limitation apply: Make sure your {{#methods}} section is directly wrapped by the GRArrayIndexHelper section.

groue commented 12 years ago

@christophercotton, I'd be happy having your feedback regarding this solution.

jasperblues commented 12 years ago

Thanks very much again for your kind support - this will do nicely.

Alternatively, I think I could create a category on my object (MyObject+Stubble or MyObject+MuttonChops ?) to make it look like it has an index property:

static char const* const indexKey = "index";

. . . . and then loop through prior to rendering to set the value. . . . heh - maybe the other way is easier ;) But I wonder if you could cook something into the template engine that makes this more seamless?

On Mar 3, 2012, at 11:12 PM, Gwendal Roué wrote:

I guess it's exactly what you want.

Actually, the Mustache language itself has no support for array indices.

That's why we need a helper object, and a dedicated section for attaching it (the ugly {{#GRArrayIndex}} in the code above). You can name this extra section the way you want. It's just a matter of attaching the helper to some template section, in which all arrays get indices.

GRArrayIndexHelper.h and GRArrayIndexHelper.m sources are at https://gist.github.com/1966553

Hope it will help, you lazy Mustachos :-)


Reply to this email directly or view it on GitHub: https://github.com/groue/GRMustache/issues/14#issuecomment-4301315

groue commented 12 years ago

I really don't know what is the best solution, honestly. The extra index property used to be my advice, until you had me play with the new helper APIs.

About your cooking question : no, this will not happen. GRMustache will keep array indices in userland as long as the Mustache language itself does not support them. Feel free to open an issue on the mustache/spec repository. All I can do is have the GRMustache API expressive enough to let users add stuff that the language itself lacks.

groue commented 12 years ago

@jasperblues GRMustache v1.12 is out, with the new GRMustacheTemplateDelegate protocol.

GRMustacheTemplateDelegate is intended to be the place where one can do wizardry that is not officially endorsed by the Mustache language itself. This is the case for arrays indices.

I'd be happy if you would try using the protocol, and check if it can help you. I haven't yet written the documentation for it, but it is used in the NumberFormatting project that you'll find in the /SampleCode directory. Let me know if you need more information.

jasperblues commented 12 years ago

Nice work! Will try today and let you now, plus pass on some notes to convert to docs.

Sent from my iPod

On 05/03/2012, at 2:53 AM, Gwendal Rouéreply@reply.github.com wrote:

@jasperblues GRMustache v1.12 is out, with the new GRMustacheTemplateDelegate protocol.

GRMustacheTemplateDelegate is intended to be the place where one can do wizardry that is not officially endorsed by the Mustache language itself. This is the case for arrays indices.

I'd be happy if you would try using the protocol, and check if it can help you. I haven't yet written the documentation for it, but it is used in the NumberFormatting project that you'll find in the /SampleCode directory. Let me know if you need more information.


Reply to this email directly or view it on GitHub: https://github.com/groue/GRMustache/issues/14#issuecomment-4312119

jasperblues commented 12 years ago

Hi Gwendal,

There's two properties on GRMustacheInvocation: returnValue and key.

Return value works for the number example, but I'm assuming key is what's needed for array indices. Is this the case?

Perhaps some Appledoc comments on the GRMustacheInvocation?

Meanwhile, I can confirm that the GRMustacheHelper approach works fine (I just copy/pasted the gist).

Kind Regards,

Jasper

On Mar 5, 2012, at 2:53 AM, Gwendal Roué wrote:

@jasperblues GRMustache v1.12 is out, with the new GRMustacheTemplateDelegate protocol.

GRMustacheTemplateDelegate is intended to be the place where one can do wizardry that is not officially endorsed by the Mustache language itself. This is the case for arrays indices.

I'd be happy if you would try using the protocol, and check if it can help you. I haven't yet written the documentation for it, but it is used in the NumberFormatting project that you'll find in the /SampleCode directory. Let me know if you need more information.


Reply to this email directly or view it on GitHub: https://github.com/groue/GRMustache/issues/14#issuecomment-4312119

groue commented 12 years ago

Cool, Jasper, happy you found your solution !

groue commented 12 years ago

Last take on the subject: https://github.com/groue/GRMustache/blob/master/Guides/sample_code/counters.md

jasperblues commented 12 years ago

Awesome guide - makes it easy enough. Can't ask for more than that.

groue commented 12 years ago

Very last take on the subject: https://github.com/groue/GRMustache/blob/master/Guides/sample_code/indexes.md (requires GRMustache4)

jasperblues commented 12 years ago

Wow, Mustacho - that's awesome.

You know what though? I'm still using the original example that you kindly gave me! . . I should upgrade it. . . but, well - you know . . . . . Tequila to drink. MariachI parties to attend. Chicken Tostadas to feast on. . . . .

On May 27, 2012, at 12:48 AM, Gwendal Roué wrote:

Very last take on the subject: https://github.com/groue/GRMustache/blob/master/Guides/sample_code/indexes.md


Reply to this email directly or view it on GitHub: https://github.com/groue/GRMustache/issues/14#issuecomment-5948088

groue commented 12 years ago

If it ain't broken, don't fix it ;-) Happy tequila Jasper!

mytharcher commented 10 years ago

Forgive me for appending suggestion on this issue. Because I didn't find any topic about this in mustache/spec.

I just want to suggest a list index syntax like this:

{{#list[index]}}
    {{index}}: {{name}}
{{/}}

The reason is it just looks like an array definition. And this can indicate the name of index as any word rather than specified word index in loop to avoid conflict with list item data itself.

The only defect is it break the section syntax just for list variables. If my idea is not comprehensive enough, just ignore this.

groue commented 10 years ago

Hi @mytharcher.

As the previous comments show, GRMustache allows the user to define its own index. If you look at the sample code, you'll see that the technique is the same whether the user wants:

Your proposal has three defects :

  1. it restricts the possibilities to 0-based indexes.
  2. it doesn't foster enough the fact that any kind of index manipulation is possible.
  3. {{# list[index] }} has the same level of verbosity as {{# withIndex(list) }}

So, I'm sorry. Thank you for your proposal, but I don't want to implement it.

Now, you may know about Handlebars.js. Handlebars is an extension to Mustache, and provides some facilities that Mustache doesn't, just as GRMustache. Among Handlebars extensions is the special key @index, which resolves to the current index in a loop. This gives:

{{! Handlebars template }}
{{#each list}}
  {{@index}}: {{name}}
{{/each}}

So why not adding to GRMustache built-in support for 0-based indexes. But this would be done without any special syntax, just as in Handlebars:

{{! Hypothetic GRMustache template }}
{{#list}}
  {{@index}}: {{name}}
{{/}}

Today I don't feel enough user pressure for implementing this. The sample code for rendering indexes looks like it's enough (it works, and versatile enough for making users happy).

mytharcher commented 10 years ago

Thanks for your explanation.