Search the documentation
 Show GitHub edit links  Hide GitHub edit links
In OpenCms since: 6.0 Documented since: 9.0 Latest revision for: 9.0 Valid for OpenCms: 10.5.3

We show a dynamic function that collects items and allows linking to a detail view of each item.

The result

Click on the headings of the list entries to see their detail views. If you are offline, you might also change some parameters of the function that provides the list.

In the detail view a special formatter is used. It displays the title, the text and the image, if present. Hence, it may happen that the content says "Do something!" - but you simply can't because of the different formatter that is used. Or the article might describe somethings that's not true for its detail view formatter.

Example resources and the interesting spots

In this demo different things are of interest:

  • How to build the list?
  • How to add a detail page for a type?
  • How to configure the naming scheme for the URLs of detail pages?

We discuss these questions in the following subsections.

How the list is created

The list, shown in the example is generated by a dynamic function. The function provider looks as follows:

In the dynamic function that uses the provider, the parameter's folder, type and count are specified. If offline, click on the function's edit point in the result section.
<%@page buffer="none" session="false" trimDirectiveWhitespaces="true" taglibs="c,cms,fn" %>
<cms:formatter var="con" rdfa="rdfa">
	<div>
		<div class="headline"><h3 ${rdfa.Title}><c:out value="${con.value.Title}" escapeXml="false" /></h3></div>
		<c:set var="folder">
			<c:choose>
			<c:when test="${fn:startsWith(param.folder,'/system') or fn:startsWith(param.folder,'/shared')}">
				${param.folder}
			</c:when>
			<c:otherwise>
				${cms.requestContext.siteRoot}${param.folder}
			</c:otherwise>
			</c:choose>
		</c:set>
		<%-- Define a Solr query --%>
		<c:set var="solrQuery">fq=parent-folders:"${folder}"&fq=type:${param.type}&rows=${param.count}&sort=lastmodified desc</c:set>
		<%-- Define a create path --%>
		<c:set var="createPath">${param.folder}</c:set>
		<%-- Collect the resources --%>
		<cms:contentload collector="byContext" param='${solrQuery}|createPath=${createPath}article_%(number).xml' 
		                 preload="true" >
			<cms:contentinfo var="info" />
			<c:choose>
			<c:when test="${info.resultSize > 0}">
				<cms:contentload editable="true">
					<cms:contentaccess var="content" />
					<div>
						<h4><a href="<cms:link>${content.filename}</cms:link>">${content.value.Title}</a></h4>
						<hr />
					</div>
				</cms:contentload>
			</c:when>
			<c:otherwise>
				Nothing found for query:<br/><em>${solrQuery}</em>
			</c:otherwise>
			</c:choose>
		</cms:contentload>
	</div>
</cms:formatter>

The most interesting part is the <cms:contentload>-tag. It is used twice. Once, in the "outer" use, with preload="true" as an attribute and the attributes collector and param. The collector attribute specifies which collector is used and the param attribute configures the collector. In the example, we use the Solr-collector byQuery and configure it with a Solr query and (after the |) with the path and a name scheme that specifies where and under which name new resources are created.

Setting preload to true avoids loading the resources completely. The loaded information suffices to know, e.g., the number of results, as is read via info.resultSize from the info object exposed by <cms:contentinfo var="info" />. If we have at least one result, we start loading the content fully by the "inner" <cms:contentload>. It takes over collector and param from the outer tag and the additional attribute editable="true" enables us to edit, add and delete list entries.

The "inner" <cms:contentload>'s body is looped through for each collected content item and via <cms:contentaccess> we get access to the current content in the same way we get access to content in a formatter. The link to ${content.filename} by default links to the content itself. But, if a detail page for content of that type is configured, <cms:link> redirects the link to this detail page.

How the detail page is added

If detail pages for a content type are allowed (what is configured in the module configuration of the module where the resource type is defined), you can add a detail page via the sitemap editor. Therefore, go to the sitemap editor, open the "Add wizard" and choose the tab "Detail pages". Now you can select the detail page for your type and drop it in the sitemap.

In the example, we added the page "Article detail pages" as the detail page for the type "documentation-demo-article". The page is marked as such a detail page in the sitemap by stating the type in brackets and using the type's icon for the page entry:

How the URL name is adjusted

While the first part of the URL of the detail view of an article is quite clear, it is the detail page's URL, the last, content-specific part, that is not that obvious. In the demo, it is generated from the article's Title elements. This behavior is configured in the content type definition of the article. In the <appinfo>-part, a mapping from the Title element to urlName is configured:

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
	elementFormDefault="qualified">

	<xsd:include schemaLocation="opencms://opencms-xmlcontent.xsd" />

	<xsd:element name="DocumentationDemoArticles" type="OpenCmsDocumentationDemoArticles" />

	<xsd:complexType name="OpenCmsDocumentationDemoArticles">
		<xsd:sequence>
			<xsd:element name="DocumentationDemoArticle" type="OpenCmsDocumentationDemoArticle"
				minOccurs="0" maxOccurs="unbounded" />
		</xsd:sequence>
	</xsd:complexType>

	<xsd:complexType name="OpenCmsDocumentationDemoArticle">
		<xsd:sequence>
			<xsd:element name="Title" type="OpenCmsString" />
			<xsd:element name="Text" type="OpenCmsHtml" />
			<xsd:element name="Image" type="OpenCmsVfsImage" minOccurs="0" />
			<xsd:element name="Script" type="OpenCmsString" minOccurs="0" />
			<xsd:element name="PDF" type="OpenCmsVfsFile" minOccurs="0" />
		</xsd:sequence>
		<xsd:attribute name="language" type="OpenCmsLocale" use="optional" />
	</xsd:complexType>

	<xsd:annotation>
		<xsd:appinfo>
			<layouts>
				<layout element="Script" widget="TextareaWidget" configuration="10" />
			</layouts>
			<mappings>
				<mapping element="Title" mapto="urlName" />
			</mappings>
		</xsd:appinfo>
	</xsd:annotation>
</xsd:schema>	  

It is possible to map every other element instead of Title. If no element is mapped, the resource-id of the article content would be used for the content-specific URL part.

You can improve this page

Please contribute your suggestions or comments regarding this topic on our wiki. For support questions, please use the OpenCms mailing list or go for professional support.