Use the Content Blocks Plugin in the Delivery Tier

Content Bean

The setup application's Beanwriter tool does not support the Content Blocks plugin yet, therefore when adding a content blocks field to a document type, the corresponding content bean class must be updated manually.

Each compound type used must have its own bean class as well (the Beanwriter will take care of this).

For the actual content blocks field, there are two approaches: one multi-type list or list for each type.

Single Multi-Type List

The first approach is to add one method to the bean which simply returns a list of all the content blocks, and deal with the different types of blocks in the template.

Advantage: the content blocks can be rendered in the exact order they are stored in the document.

Disadvantage: the template must "know" some implementation logic (no strict separation of concerns).

For example, for a content blocks field called blocks in a namespace myproject:

    public List<?> getBlocks() {
        return getChildBeansByName("myproject:blocks");
    }

If standard (out of the box) compound types are used the hst:isBeanType function can be used 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>
Note that hst:isBeanType returns true for the specified bean class as well as any class that descends from it. Therefor always check descendants before their ancestors.

If custom compound types are used (i.e. their bean classes are in the same project) a property can be added to their bean classes, e.g.:

@Node(jcrType="myproject:videoblock")
public class VideoBlock extends HippoCompound {

    // used to differentiate between different types of content blocks
    public String getType(){
        return "video";
    }

    public String getVideo() {
        return getProperty("myproject:video");
    }
}

The type property can then be used in the template to check the content block's 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

The second approach is to add a get method to the content bean for each block type.

Advantage: cleaner template, better separation of concerns.

Disadvantage: the order of the different content blocks is lost.

Example:

public List<?> getVideos() {
    // argument is the type of the compound
    return getChildBeans("myproject:videoblock");
}

public List<?> getImages() {
    return getChildBeans("myproject:imageblock");
}

The template can then render the content blocks by type:

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>
Did you find this page helpful?
How could this documentation serve you better?
On this page
    Did you find this page helpful?
    How could this documentation serve you better?