Use the Content Blocks Plugin in the Delivery Tier
Content Bean
The Beanwriter tool in the setup application does not currently support the Content Blocks plugin. When you add a content blocks field to a document type, you must manually update the corresponding content bean class.
Each compound type used in your content blocks field also requires its own bean class. The Beanwriter tool will generate these classes for you.
For the content blocks field itself, you can choose between two approaches: a single multi-type list or a separate list for each type.
Single Multi-Type List
In this approach, add a method to your bean that returns a list containing all content blocks. You then handle the different block types in your template.
Advantages:
- Content blocks are rendered in the same order as they are stored in the document.
Disadvantages:
- The template must contain logic to handle different block types, which reduces separation of concerns.
For example, if you have a content blocks field named blocks in the myproject namespace:
public List<?> getBlocks() { return getChildBeansByName("myproject:blocks"); }
If you use standard compound types provided out of the box, you can use the hst:isBeanType function (see hst-core-tags/isBeanType.fn.html in the HST Tag Library) to check a content block's type in the template.
Freemarker:
<#if document.blocks??> <#list document.blocks as block> <#if hst.isBeanType(block, 'org.hippoecm.hst.content.beans.standard.HippoMirror')> <!-- render link --> <#elseif hst.isBeanType(block, 'org.hippoecm.hst.content.beans.standard.HippoHtml')> <!-- render rich text --> </#if> </#list> </#if>
JSP:
<c:if test="${not empty requestScope.document.blocks}"> <c:forEach var="item" items="${requestScope.document.blocks}"> <c:choose> <c:when test="${hst:isBeanType(item, 'org.hippoecm.hst.content.beans.standard.HippoMirror')}"> // render link </c:when> <c:when test="${hst:isBeanType(item, 'org.hippoecm.hst.content.beans.standard.HippoHtml')}"> // render rich text </c:when> </c:choose> </c:forEach> </c:if>
hst:isBeanType returns true for the specified bean class and any subclasses. Always check for the most specific types before their ancestors.
If you use custom compound types (with bean classes in your project), you can add a property to each bean class to identify the block type. For example:
@Node(jcrType="myproject:videoblock") public class VideoBlock extends HippoCompound { // Used to differentiate between content block types public String getType(){ return "video"; } public String getVideo() { return getProperty("myproject:video"); } }
You can then reference the type property in your template to determine the block type.
Freemarker:
<#if document.blocks??> <#list document.blocks as block> <#if block.type == 'video'> <!-- render video --> <#elseif block.type == 'image'> <!-- render image --> </#if> </#list> </#if>
JSP:
<c:if test="${not empty requestScope.document.blocks}"> <c:forEach var="item" items="${requestScope.document.blocks}"> <c:choose> <c:when test="${item.type=='video'}"> // render video </c:when> <c:when test="${item.type=='image'}"> // render image </c:when> </c:choose> </c:forEach> </c:if>
List Per Type
In this approach, add a separate getter method to the content bean for each block type.
Advantages:
- The template is cleaner and has better separation of concerns.
Disadvantages:
- The original order of the content blocks is not preserved.
Example implementation:
public List<?> getVideos() { // Argument is the compound type return getChildBeans("myproject:videoblock"); } public List<?> getImages() { return getChildBeans("myproject:imageblock"); }
You can then render content blocks by type in your template.
Freemarker:
<#if document.videos??> <#list document.videos as video> <!-- render video --> </#list> </#if> <#if document.images??> <#list document.images as image> <!-- render image --> </#list> </#if>
JSP:
<c:if test="${not empty requestScope.document.videos}"> <c:forEach var="item" items="${requestScope.document.videos}"> // render video </c:forEach> </c:if> <c:if test="${not empty requestScope.document.images}"> <c:forEach var="item" items="${requestScope.document.images}"> // render image </c:forEach> </c:if>