Go to main content

Kentico macro repeater

Over the years, the macro engine in Kentico has become a mighty tool that serves you data from all corners of the CMS. What I love the most is that they don't limit much where you write them and what information you request. Moreover, with a single macro expression, you can substitute a whole web part. Today, in our case, we will humiliate the Repeater web part.

Kentico macro repeater

No doubt, the Repeater web part is an essential component of the Kentico template development mix. Regrettably, the only place you can use it is a web part zone. On the other hand, macros could be resolved anywhere. Web part properties, email widgets, page layouts, On-line forms, etc.
In simple words, the Repeater web part based on multiple conditions and transformation renders pages data. Although it has a tremendous number of properties that specify the output, I find myself using just a few of them in most cases. In the image below you can see typical Repeater web part setup. 

This could be substituted by a macro expression. Below you can find a macro setup that corresponds to the Repeater web part above.

{% 
    type = "Custom.PageType";
    path = CurrentDocument.NodeAliasPath + "/%";
    nestingLevel = CurrentDocument.NodeLevel.ToInt() + 2;
    transformation = "Custom.PageType.Item";   
    orderBy = "NodeOrder";    
    columns = "DocumentName, NodeAliasPath";

    Documents  
        .ClassNames(type)           
        .Where("NodeAliasPath LIKE '" + path + "' AND NodeLevel < " + nestingLevel)
        .OrderBy(orderBy)
        .Columns(columns)
        .WithAllData
        .ApplyTransformation(transformation); 
#%}

Path & Maximum nesting level

In the macro, both properties are specified inside the Where clause because the macro API doesn't have specific methods that would operate them. In the background, both Path and Maximum nesting level, are compared directly in the database to columns in the View_CMS_Tree_Joined view. That is the reason why the Path is specified differently:

  • ./% in Repeater
  • CurrentDocument.NodeAliasPath + "/%" in macro

As well as Maximum nesting level:

  • 1 in Repeater
  • CurrentDocument.NodeLevel.ToInt() + 2 in macro

Check the documentation to get the whole picture of the API

Performance 

When using the Repeater web part, Kentico advises you to specify the Columns property to those you really use in the transformation. This will limit data obtained from the database and make the page processing faster.
You can take the same approach with the Macro repeater. However, the situation gets shady because of the WithAllData clause. Let me explain a little bit what happens behind the curtains if you specify or omit the WithAllData or Columns clauses.

Without WithAllData, without Columns specified

All columns from View_CMS_Tree_Joined are selected.

Without WithAllData, with Columns specified

DocumentName, ClassName, NodeACLID, NodeSiteID, NodeOwner, DocumentCulture, NodeParentID, DocumentID, NodeID columns are selected + those that are specified in the Columns clause from View_CMS_Tree_Joined. In case specified columns are not part of the
View_CMS_Tree_Joined view, no output gets rendered and an exception appears in the Event log application.

With WithAllData, without Columns specified

All columns from View_CMS_Tree_Joined and coupled table defined by the ClassName clause are selected.

With WithAllData, with Columns specified

All columns from coupled table defined by the ClassName clause are selected and DocumentName, ClassName, NodeACLID, NodeSiteID, NodeOwner, DocumentCulture, NodeParentID, DocumentID, NodeID columns + those that are specified in the Columns clause from the View_CMS_Tree_Joined view are selected as well.

Regarding performance, I should mention that macros could be cached, see the documentation.

What about custom tables?

Oh, yes, you can do such fancy stuff with custom tables as well. In the example below, we repeat custom table data based on a where condition and a transformation:

{% 
	whereCondition = "ItemID=0";
	transformation = "Custom.Table.Item";

	CMSContext.Current.GlobalObjects.CustomTables["Custom.Table"].Items
		.Where(whereCondition)
		.ApplyTransformation(transformation)
#%}

Final thoughts

The Kentico macro repeater approach gives you flexibility where you render the output and could save you from writing custom web parts. Having the performance tweaks explained, you can start using it in your projects as well.

Milan Lund

is a freelance web developer and a proud Basenji owner. His specialties are Kentico CMS/EMS and Kentico Cloud.

Further reading

all posts