Tridion allows your authors to add as many Components to each Page of your website as they like, in any order, using any combination of the templates you provide.
For example:
Article teaser Article teaser Download with thumbnail Download with thumbnail Download with thumbnail
This represents a page containing five Components using two ComponentTemplates. There is nothing wrong with this until you want to do something radical like surround the Download Components with their own wrapper div tag.
<div id="downloads"> {THE DOWNLOADS GO HERE} </div>
To achieve this, you could put some specific logic in the Page Template so that whenever it encounters a group of Download Components it knows to put the wrapper div around them. The downside of this kind of approach is that you end up with a Page Template peppered with these kinds of exceptions.
Use your OrdinalPosition, dummy
A far better way is to handle this within the Component Templates themselves, so they are intelligent enough to surround themselves with extra markup if necessary.
The Tridion Object Model contains a property called OrdinalPosition. This is the index of each ComponentPresentation on the Page.
Using OrdinalPosition we can check whether the Component Template at the current index is different to the previous (or next) one.
Then all we need is a little logic to insert some HTML before and after the group of ComponentPresentations, thereby wrapping the group automagically.
Below is a function WrapComponentPresentation() which does exactly that. It should be used as follows:
WrapComponentPresentation(Page, ComponentPresentation, "<li>I am a Component</li>", "<ul>", "</ul>")
The function should be called from within the Component Template that forms the group of items – in this case our ‘Download with thumbnail’ template.
Then you can add multiple Components to the Page, all using the same template, and the first/last Components will intelligently prepend/append code where necessary.
Job done!
Function WrapComponentPresentation(objPage, objComponentPresentation, strComponentPresentation, strBefore, strAfter) Dim strTemp, numPosition, numOfCPsOnPage numPosition = objComponentPresentation.OrdinalPosition numOfCPsOnPage = objPage.ComponentPresentations.Count Dim boolStartOfBlock, boolEndOfBlock boolStartOfBlock = false boolEndOfBlock = false if numPosition = 1 Then boolStartOfBlock = true End if if numPosition = numOfCPsOnPage Then boolEndOfBlock = true End if if boolStartOfBlock = false Then Dim objPreviousComponent Set objPreviousComponent = objPage.ComponentPresentations(numPosition-1) if objPreviousComponent.ComponentTemplate.ID <> ComponentTemplate.ID Then boolStartOfBlock = true End if Set objPreviousComponent = Nothing End if if boolEndOfBlock = false Then Dim objNextComponent Set objNextComponent = objPage.ComponentPresentations(numPosition+1) if objNextComponent.ComponentTemplate.ID <> ComponentTemplate.ID Then boolEndOfBlock = true End if Set objNextComponent = Nothing End if if boolStartOfBlock = true Then strTemp = strTemp & strBefore End if strTemp = strTemp & strComponentPresentation if boolEndOfBlock = true Then strTemp = strTemp & strAfter End if WrapComponentPresentation = strTemp End Function