Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

Render index in loop #14

Closed
jasperblues opened this Issue Mar 3, 2012 · 18 comments

Comments

Projects
None yet
3 participants

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?

Owner

groue commented Mar 3, 2012

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);
Owner

groue commented Mar 3, 2012

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 :-)

Owner

groue commented Mar 3, 2012

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.

Owner

groue commented Mar 3, 2012

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

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";

  • (void) setIndex:(int)index {
    objc_setAssociatedObject(self, indexKey, [NSNumber numberWithInt:index];
    OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
  • (int) index {
    NSNumber index = objc_getAssociatedObject(self, indexKey);
    return [index intValue];
    }

. . . . 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:
#14 (comment)

Owner

groue commented Mar 4, 2012

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.

Owner

groue commented Mar 4, 2012

@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.

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:
#14 (comment)

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:
#14 (comment)

Owner

groue commented Mar 5, 2012

Cool, Jasper, happy you found your solution !

@groue groue closed this Mar 5, 2012

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

Owner

groue commented May 26, 2012

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

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:
#14 (comment)

Owner

groue commented May 27, 2012

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

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.

Owner

groue commented Dec 21, 2013

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:

  • 0-based indexes,
  • 1-based indexes,
  • periodic counters (0,1,0,1,... or 0,1,2,0,1,2,... etc.),
  • isolate 1st or last element
  • any other index manipulation

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).

Thanks for your explanation.

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