Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 159 lines (110 sloc) 6.419 kB
bd53b5f @groue Obsolete number formatting and localization sample code
authored
1 [up](../../../../tree/master/Guides/sample_code), [next](../forking.md)
438ce09 @groue indexes.md guide
authored
2
0803300 @groue Collection Indexes Sample Code update
authored
3 Collection Indexes
4 ==================
438ce09 @groue indexes.md guide
authored
5
e741dbc @groue Rewrite indexes sample code with filters (WIP)
authored
6 In a genuine Mustache way
f9dc2e2 @groue Restore indexes.md
authored
7 -------------------------
e741dbc @groue Rewrite indexes sample code with filters (WIP)
authored
8
0803300 @groue Collection Indexes Sample Code update
authored
9 Mustache is a simple template language. Its [specification](https://github.com/mustache/spec) does not provide any built-in access to collection indexes. It does not provide any way to render a section at the beginning of a loop, and another section at the end. It does not help you render different sections for odd and even indexes.
438ce09 @groue indexes.md guide
authored
10
11 If your goal is to design your templates so that they are compatible with [other Mustache implementations](https://github.com/defunkt/mustache/wiki/Other-Mustache-implementations), the best way to render indices and provide custom looping logic is to have each of your data objects provide with its index, regardless of how tedious it may be for you to prepare the rendered data.
12
e741dbc @groue Rewrite indexes sample code with filters (WIP)
authored
13 For instance, instead of `[ { name:'Alice' }, { name:'Bob' } ]`, you would provide: `[ { name:'Alice', position:1, isFirst:true, isOdd:true }, { name:'Bob', position:2, isFirst:false, isOdd:false } ]`.
438ce09 @groue indexes.md guide
authored
14
bc112a1 @groue Rewrite indexes sample code with filters (WIP)
authored
15
1d8cb17 @groue Rewritten indexes.md guide, so that it matches the code refactoring o…
authored
16 GRMustache solution
17 -------------------
438ce09 @groue indexes.md guide
authored
18
19f0f57 @groue Link from guide to sample project
authored
19 **[Download the code](../../../../tree/master/Guides/sample_code/indexes)**
3f50ab0 @groue Links to sample code projects hosted at https://github.com/groue/GRMu…
authored
20
1d8cb17 @groue Rewritten indexes.md guide, so that it matches the code refactoring o…
authored
21 You can have Mustache templates render positional keys like `position` or `isFirst` for you, and avoid preparing your data.
438ce09 @groue indexes.md guide
authored
22
657c934 @groue Mandatory warning against other Mustache implementations
authored
23 **However, it may be tedious or impossible for other Mustache implementations to produce the same rendering.**
24
25 So check again the genuine Mustache way, above. Or keep on reading, now that you are warned.
26
0803300 @groue Collection Indexes Sample Code update
authored
27 ### The rendering
e3ca5bd @groue Rewrite indexes sample code with filters (WIP)
authored
28
0803300 @groue Collection Indexes Sample Code update
authored
29 Below we'll implement the special keys `position`, `isFirst`, and `isOdd`:
438ce09 @groue indexes.md guide
authored
30
59c121a @groue Collection Indexes Sample Code update
authored
31 `Document.mustache`:
32
438ce09 @groue indexes.md guide
authored
33 <ul>
bc112a1 @groue Rewrite indexes sample code with filters (WIP)
authored
34 {{# withPosition(people) }}
1d8cb17 @groue Rewritten indexes.md guide, so that it matches the code refactoring o…
authored
35 <li class="{{# isOdd }}odd{{/ isOdd }} {{# isFirst }}first{{/ isFirst }}">
bc112a1 @groue Rewrite indexes sample code with filters (WIP)
authored
36 {{ position }}:{{ name }}
37 </li>
38 {{/ withPosition(people) }}
438ce09 @groue indexes.md guide
authored
39 </ul>
40
59c121a @groue Collection Indexes Sample Code update
authored
41 `Render.m`:
bc112a1 @groue Rewrite indexes sample code with filters (WIP)
authored
42
43 ```objc
59c121a @groue Collection Indexes Sample Code update
authored
44 id data = @{
45 @"people": @[
46 @{ @"name": @"Alice" },
47 @{ @"name": @"Bob" },
48 @{ @"name": @"Craig" },
49 ],
50 @"withPosition": [PositionFilter new]
51 };
52
53 NSString *rendering = [GRMustacheTemplate renderObject:data
54 fromResource:@"Document"
55 bundle:nil
56 error:NULL];
438ce09 @groue indexes.md guide
authored
57 ```
58
0803300 @groue Collection Indexes Sample Code update
authored
59 Final rendering:
60
61 <ul>
62 <li class="odd first">
63 1:Alice
64 </li>
65 <li class=" ">
66 2:Bob
67 </li>
68 <li class="odd ">
69 3:Craig
70 </li>
71 </ul>
72
73
74 ### PositionFilter implementation
e3ca5bd @groue Rewrite indexes sample code with filters (WIP)
authored
75
1d8cb17 @groue Rewritten indexes.md guide, so that it matches the code refactoring o…
authored
76 You may just skip the rest of this document, and [download the `PositionFilter` class](../../../../tree/master/Guides/sample_code/indexes). It should be trivial to adapt, should you need the `isLast` property, for example.
77
0803300 @groue Collection Indexes Sample Code update
authored
78 Let's see how it is implemented.
e741dbc @groue Rewrite indexes sample code with filters (WIP)
authored
79
9ce6ce6 @groue Typo
authored
80 Due to the parenthesis in the `withPosition(people)` expression, we know that it is a [filter](../filters.md), an object that conforms to the `GRMustacheFilter` protocol:
e741dbc @groue Rewrite indexes sample code with filters (WIP)
authored
81
82 ```objc
59c121a @groue Collection Indexes Sample Code update
authored
83 /**
0803300 @groue Collection Indexes Sample Code update
authored
84 * A filter that renders its array argument with the extra following keys
85 * defined for each item:
59c121a @groue Collection Indexes Sample Code update
authored
86 *
87 * - position: returns the 1-based index of the item
88 * - isOdd: returns YES if the position of the item is odd
89 * - isFirst: returns YES if the item is at position 1
90 */
e741dbc @groue Rewrite indexes sample code with filters (WIP)
authored
91 @interface PositionFilter : NSObject<GRMustacheFilter>
92 @end
93 ```
94
0803300 @groue Collection Indexes Sample Code update
authored
95 The protocol requires the `transformedValue:` method, that returns the result of the filter.
1d8cb17 @groue Rewritten indexes.md guide, so that it matches the code refactoring o…
authored
96
0803300 @groue Collection Indexes Sample Code update
authored
97 Since we need a custom rendering of the array, the result of the filter will conform to the `GRMustacheRendering` protocol (see the [Rendering Objects Guide](../rendering_objects.md)).
659c741 @groue Collection Indexes Sample Code update
authored
98
40e204b @groue Better links to "context stack" definition
authored
99 Rendering objects take full responsability of their rendering. Our will render the section tag as many times as the array has items, extending the [context stack](../runtime.md#the-context-stack) with both a dictionary containing the special keys, and the array items that will provide the `name` key.
e741dbc @groue Rewrite indexes sample code with filters (WIP)
authored
100
101 ```objc
102 @implementation PositionFilter
103
104 /**
59c121a @groue Collection Indexes Sample Code update
authored
105 * The transformedValue: method is required by the GRMustacheFilter protocol.
106 *
107 * Don't provide any type checking, and assume the filter argument is an array:
e741dbc @groue Rewrite indexes sample code with filters (WIP)
authored
108 */
59c121a @groue Collection Indexes Sample Code update
authored
109
110 - (id)transformedValue:(NSArray *)array
e741dbc @groue Rewrite indexes sample code with filters (WIP)
authored
111 {
0803300 @groue Collection Indexes Sample Code update
authored
112 // We want to provide custom rendering of the array.
113 //
114 // So let's return an object that does custom rendering.
e741dbc @groue Rewrite indexes sample code with filters (WIP)
authored
115
bb45983 @groue Collection Indexes Sample Code update
authored
116 return [GRMustache renderingObjectWithBlock:^NSString *(GRMustacheTag *tag, GRMustacheContext *context, BOOL *HTMLSafe, NSError *__autoreleasing *error)
117 {
59c121a @groue Collection Indexes Sample Code update
authored
118 NSMutableString *buffer = [NSMutableString string];
119
120 [array enumerateObjectsUsingBlock:^(id item, NSUInteger index, BOOL *stop) {
121
bb45983 @groue Collection Indexes Sample Code update
authored
122 // Have our "specials" keys enter the context stack,
123 // so that the `{{ position }}` tags etc. can render:
59c121a @groue Collection Indexes Sample Code update
authored
124
125 id specials = @{
126 @"position": @(index + 1),
127 @"isFirst" : @(index == 0),
128 @"isOdd" : @(index % 2 == 0),
129 };
130 GRMustacheContext *itemContext = [context contextByAddingObject:specials];
131
132
bb45983 @groue Collection Indexes Sample Code update
authored
133 // Have the item itself enter the context stack,
134 // so that the `{{ name }}` tag can render:
59c121a @groue Collection Indexes Sample Code update
authored
135
136 itemContext = [itemContext contextByAddingObject:item];
137
138
bb45983 @groue Collection Indexes Sample Code update
authored
139 // Render the item:
59c121a @groue Collection Indexes Sample Code update
authored
140
141 NSString *itemRendering = [tag renderContentWithContext:itemContext HTMLSafe:HTMLSafe error:error];
142 [buffer appendString:itemRendering];
143 }];
144
145 return buffer;
e741dbc @groue Rewrite indexes sample code with filters (WIP)
authored
146 }];
147 }
148
149 @end
150 ```
151
bfd6b3c @groue More links to Reference from Guides
authored
152 See the [GRMustacheTag Class Reference](http://groue.github.io/GRMustache/Reference/Classes/GRMustacheTag.html) and [GRMustacheContext Class Reference](http://groue.github.io/GRMustache/Reference/Classes/GRMustacheContext.html) for a full documentation of GRMustacheTag and GRMustacheContext, and details on the `contextByAddingObject:` and `renderContentWithContext:HTMLSafe:error:` methods.
153
0803300 @groue Collection Indexes Sample Code update
authored
154 Writing [filters](../filters.md) that return [rendering objects](../rendering_objects.md) lead to code that is pretty close to the [Handlebars.js block helpers](http://handlebarsjs.com/block_helpers.html). You may enjoy comparing the code above to the [`each_with_index` Handlebars helper](https://gist.github.com/1048968).
438ce09 @groue indexes.md guide
authored
155
c1aaf13 @groue More links from guides to sample projects
authored
156 **[Download the code](../../../../tree/master/Guides/sample_code/indexes)**
157
bd53b5f @groue Obsolete number formatting and localization sample code
authored
158 [up](../../../../tree/master/Guides/sample_code), [next](../forking.md)
Something went wrong with that request. Please try again.