I was reviewing a solution I’ve been working on and noticed that at one point I was pushing out a ‘QuantityOfListItems’ from C# into the package – and couldn’t recall why.
On further investigation I saw that I was using this in the DWT to detect when I was on the last list item so I could compare this with the TemplateRepeatIndex value. Although it all worked fine it felt like overkill to rely on C# for something so trivial and didn’t add any value so I had a scoot around.
I found a CollectionLength built-in function that looked like it might be just what the Dr. ordered…
So… the reason for the post… It took quite some phaffing to tweak the syntax for this – just due to the fact I’ve had my head in C# code more than I have DWT lately so I thought I’d share it!
All I need to do is check
- if the current index of the item in the repeatable field is the first then print the opening tags
- write out the repeated syntax/value for each instance of the repeatable field
- if the current index of the item in the repeatable field is the last then print the closing tags
<!-- TemplateBeginRepeat name="Component.Fields.repeatField" --> <!-- TemplateBeginIf cond = "TemplateRepeatIndex == 0 " --> <ul> <!-- TemplateEndIf --> <li>@@Field@@</li> <!-- TemplateBeginIf cond = "TemplateRepeatIndex == @@CollectionLength("repeatField")@@" --> </ul> <!-- TemplateEndIf --> <!-- TemplateEndRepeat -->
OK, so the obvious error – TemplateRepeatIndex is 0 based whilst the CollectionLength returns a 1 based  result! The other syntax is pretty standard so we’ll concentrate on the test for the last index item.
<!-- TemplateBeginIf cond = "TemplateRepeatIndex == @@CollectionLength("repeatField")-1@@" -->
No Joy. So I have another scoot around and find an interesting StackOverflow post reminding me the value returned is a string. As we need to perform an integer calculation and comparison we need to parse the value to an integer.
<!-- TemplateBeginIf cond = "TemplateRepeatIndex == @@parseInt(${CollectionLength("repeatField")})@@-1" -->
Now I’m using the debug method Frank van Puffelen describes in his StackOverflow posting and all appears well – I can see the CollectionLength and the TemplateRepeatIndex are both 1 and the end tag still isn’t written out.
See the deliberate error (well it wasn’t deliberate and it was one of those annoyingly simple things that I’m sure others will trip up on!). Â Although our first comparison with TemplateRepeatIndex and == 0 above is with an integer and it works as we want (even if the comparison is against a non-zero integer) I figured I’d try to parseInt the TemplateRepeatIndex…
<!-- TemplateBeginRepeat name="Component.Fields.repeatField" --> <!-- TemplateBeginIf cond = "TemplateRepeatIndex == 0 " --> <ul> <!-- TemplateEndIf --> <li>@@Field@@</li> <!-- TemplateBeginIf cond = "@@parseInt(TemplateRepeatIndex)@@ == @@parseInt(${CollectionLength("repeatField")})@@-1" --> </ul> <!-- TemplateEndIf --> <!-- TemplateEndRepeat -->
Success!
Hopefully this simple pattern can assist you in not having to resort to C# as I’d figured I had to originally.
Just discovered:
If you’re 2011 SP1 HR1 there is a hotfix, CM_2011.1.1.81739, available and to quote the description:
“TemplateRepeatIndex is based on a text content type and therefore not allowing an expression like the following; @@TemplateRepeatIndex+1@@ this would result in string concatenation.
TemplateRepeatIndex will now be stored as a numeric value within the package.
”
So now you have an option of installing the “hotfix” or using the above if this isn’t feasible in your environment.
Tridion Practice has since moved to Github. You may wish to update your link to point to https://github.com/TridionPractice/tridion-practice/wiki/BuiltInFunctionsForUseInHtmlTemplates
Update – thanks very much for the note Dom!