Skip to main content

Working with a collection of assets

Worked example

This compares three approaches to the same problem rather than documenting a single feature. Pick the one that fits your case.

There are many scenarios where you'll need to be able to iterate over a collection of assets within the CMS. For example, you may require the ability to generate links to several items within a Folder as part of a navigation menu. Another common scenario includes being able to list something like the top most recent news articles on a page.

Whatever the use case is, there are a number of different ways in which you could approach this. In the sections that follow, we'll cover some different methods you can use to ultimately retrieve and output the same information from a collection of Page assets.

For the samples that follow, consider the existing folder/asset hierarchy:

  • folderA
    • page1
    • page2
    • page3

The idea here is that given a setup as described above, we want to:

  1. Iterate over all of the Page assets in the Folder
  2. For each Page we encounter, output a link to it
  3. Use each Page's Display Name for the link text
  4. Make the links part of an unordered list

For the final output, the goal will be to produce the following HTML:

XML
<ul>
 <li>
  <a href="site://siteName/folderA/page1">Display Name for page1</a>
 </li>
 <li>
  <a href="site://siteName/folderA/page2">Display Name for page2</a>
 </li>
 <li>
  <a href="site://siteName/folderA/page3">Display Name for page3</a>
 </li>
</ul>

Using the Locator Tool (Velocity)

If the items you want to access are all contained within a particular Folder, you can use the Locator Tool to access that Folder and then iterate over the child assets within it.

Velocity
#set ($folder = $_.locateFolder("folderA", "siteName"))
<ul>
#foreach ($child in $folder.children)
 <li>
  <a href="${child.link}">${child.metadata.displayName}</a>
 </li>
#end
</ul>

Using the Query API (Velocity)

The Query API is another option which will enable you to query for assets having a particular property associated with them. Given the example from above, let's say we know each of those Pages that we're after use a given Content Type called standard-page. We can query for that Content Type and output the information we need using something like this:

Velocity
#set ($query = $_.query())
#set ($query = $query.byContentType("standard page"))
#set ($query = $query.maxResults(10))
#set ($query = $query.sortDirection("desc"))
#set ($results = $query.execute())

<ul>
#foreach ($child in $results)
 <li>
  <a href="${child.link}">${child.metadata.displayName}</a>
 </li>
#end
</ul>

Tip

Querying by Content Type will return all assets using that Content Type regardless of whether they are in a particular Folder or not. You can limit to a particular Folder using the byFolderPath option of the tool. Example:
#set ($query = $query.byFolderPath("folderA"))

Using an Index Block and Format

To target items within a particular parent Folder, a combination of an Index Block and Format can also be used to produce the needed HTML output. For the purposes of this example, we'll use a Folder Index Block to target folderA (but know that it is also possible to create a Content Type Index Block as an alternative here depending on your setup).

Creating/configuring the Index Block

Create a new Index Block with the following settings (at a minimum).

Index Block Settings
Field Value Notes
Index Type Folder Index  
Index Folder folderA Choose the Folder containing the assets you need.
Depth of Index 1 Depth is 1 here as all of our assets are directly underneath the Folder. You can bump this number if you have assets within subfolders of the main Folder.
Max Rendered Assets 50 This should be set to a realistic maximum based on how many assets you expect to be retrieving.
Indexed Asset Types Pages  
Page XML Do not render page XML inline  
Indexed Asset Content Regular Content This option includes everything we need for what we're looking to produce in the final HTML.

These settings in the Index Block will produce XML like the following:

XML
<system-index-block current-time="1711644535471" name="index" type="folder">
 <system-page id="857629d2c0a8003d7e9bd9ccf9169379">
  <name>page3</name>
  <display-name>Display Name for page3</display-name>
  <path>/folderA/page3</path>
  <site>siteName</site>
  <link>site://siteName/folderA/page3</link>
 </system-page>
 <system-page id="857508eac0a8003d7e9bd9ccd887e114">
  <name>page2</name>
  <display-name>Display Name for page2</display-name>
  <path>/folderA/page2</path>
  <site>siteName</site>
  <link>site://siteName/folderA/page2</link>
 </system-page>
 <system-page id="85735ac3c0a8003d7e9bd9cc76e1d3de">
  <name>page1</name>
  <display-name>Display Name for page1</display-name>
  <path>/folderA/page1</path>
  <site>siteName</site>
  <link>site://siteName/folderA/page1</link>
 </system-page>
</system-index-block>

Now, we can target the information from the XML using the XPathTool in Velocity or in an XSLT Format. Examples of both options can be found below:

Velocity

Velocity
#set ($pages = $_XPathTool.selectNodes($contentRoot, "system-page"))

<ul>
#foreach ($page in $pages)
 <li>
 <a href="${page.getChild('link').value}">${page.getChild('display-name').value}</a>
 </li>
#end
</ul>

XSLT

XML
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 <xsl:template match="system-index-block">
  <ul>
   <xsl:apply-templates select="system-page"/>
  </ul>
 </xsl:template>
 <xsl:template match="system-page">
  <li>
   <a>
    <xsl:attribute name="href"><xsl:value-of select="link"/></xsl:attribute>
    <xsl:value-of select="display-name"/>
  </a>
 </li>
 </xsl:template>
</xsl:stylesheet>