The Solution to Hardcoding Component Template IDs in Nested Component Presentations

Sometimes we have a need to render a nested Component using its Component Template.  The Tridion API provides us with the following function:

@@RenderComponentPresentation(nestComp.ID, "tcm:x-y-z")@@

Now, the problem with the above is that if we hardcode TCM IDs all over the place, our template becomes non-Content Porter friendly. If we port this thing from our DEV CM to QA and PROD CMs, then we have to have a step in our deployment procedure runbook to update the TCM IDs everywhere where this is done.

One way to solve this is to provide the ability to refer to the nested Component Template by name instead of the TCM ID.  So the template code will look as follows:

@@RenderComponentPresentation(nestComp.ID, "${myNestedCTName}")@@

This can be accomplished by a simple Template Building Block that pushes the names of all the Component Templates available in the system onto the Package.  Here is the TBB and an explanation of how to use it.

When using the TBB you’ll get a list of all the Component Templates pushed on your package with the name of the template being the package key and the value being the TCM ID.


So using the TBB is simple in your layout.  If using DWT, then do a double eval on the CT name to get the package variable’s value using the “${} syntax as in the example above.

Note, the TBB removes spaces and non-alphanumeric characters from the template name because using DWT it is not possible to reference variables on the package with any of those characters (you can push a variable on the package with any name, you just can’t refer to it). So simplified names of the template appear on the package as illustrated in the screenshot of a rendered template in TemplateBuilder above.

Here is the code:

using Tridion.ContentManager.Templating;
using Tridion.ContentManager.Templating.Assembly;
using System.Collections.Generic;
using System;
using Tridion.ContentManager.CommunicationManagement;
using Tridion.ContentManager;
using System.Xml.Linq;
using System.Text;
using Tridion.ContentManager.ContentManagement;
using System.Xml;
using Tridion.ContentManager.ContentManagement.Fields;
using Tridion.Extensions.ContentManager.Templating;

namespace ContentBloom.Tridion.Templating
    /// In order to be able to call @@RenderComponentPresentation(compId, cTId)@@
    /// from a DWT, we need to be able to get the CT ID by the template name.
    /// This TBB pushes all the CTs in a given publication context onto the package.
    [TcmTemplateTitle("Get Template Id By Name")]
    public class GetTemplateIdByName : TemplateBase

        public override void Transform(Engine engine, Package package)
            Initialize(engine, package);

            RepositoryItemsFilter filter = new RepositoryItemsFilter(engine.GetSession());
            filter.ItemTypes = new ItemType[] { ItemType.ComponentTemplate };
            filter.Recursive = true;

            Publication pub = this.GetPublication();
            foreach (ComponentTemplate ct in pub.GetItems(filter))
                //remove arithmetic operators so that DWT doesn't try to evaluate them
                string title = ct.Title.Replace(" ", string.Empty)
                                       .Replace("+", string.Empty)
                                       .Replace("-", string.Empty)
                                       .Replace("/", string.Empty)
                                       .Replace("*", string.Empty)
                                       .Replace("%", string.Empty)
                                       .Replace("|", string.Empty)
                                       .Replace("&", string.Empty)
                                       .Replace("[", string.Empty)
                                       .Replace("]", string.Empty)
                                       .Replace("(", string.Empty)
                                       .Replace(")", string.Empty)
                                       .Replace(">", string.Empty)
                                       .Replace("<", string.Empty)
                                       .Replace("=", string.Empty);                
                package.PushItem(title+"Template", package.CreateStringItem(ContentType.Text, ct.Id.ToString()));

Another thing to note here is that if your implementation has a gazillion templates, your package is going to get pretty heavy, so you might want to implement a parameters schema to specify the name of the nested templates you’ll be using in the parent layout, and filter your results accordingly.

2 thoughts on “The Solution to Hardcoding Component Template IDs in Nested Component Presentations

  1. Good little post Nick and something we’ve been using for a long time. We’ve got a TBB from 2008 that Nuno wrote to do this same thing with a Parameter Schema as well. It was before my time with Tridion but maybe Nuno can resurrect the source code?

  2. That one is called “Will’s double nested lookup pattern” and dates back to somewhere late 2007 IIRC.

    Great to see that it still works, because I thought the parsing of those expressions had changed over the years.

    Kudos to Will Price for coming up with it. And compliments to you for publishing it and making it more generic.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>