Folder Picker in a Hippo CMS Component

May 31st 2019 Hippo CMS Java

Hippo CMS has built-in support for configuring components through auto-generated dialogs in the Channel Editor. These can easily be defined by using annotations in the component's ParametersInfo interface. Although there's an option to open a document picker, the documentation only hints at different configurations for it. It isn't clear how to use it for picking a content folder instead of a document.

Thanks to search engines, I stumbled upon a list of supported values for the pickerConfiguration parameter mentioned in passing in a completely different section of documentation. Based on this information, I could use the Console and find the values defined in /hippo:configuration/hippo:frontend/cms/cms-pickers. Unfortunately, none of the values achieved the desired result, not even cms-pickers/folders or cms-pickers/documents-folders-only. I could still select documents in the picker, but not folders.

In the end, the correct parameter to use turned out to be pickerSelectableNodeTypes. By looking at the content in the Console, I determined that I wanted to restrict the picker to the hippostd:folder node type. Even with this parameter set, other node types (e.g. documents) are still shown in the picker but they can't be selected. Not a perfect behavior, but close enough. It's something that can be explained to the editors configuring the component.

This is the final state of my ParametersInfo interface:

public interface FolderPickerComponentInfo {

  @Parameter(
      name = "Content folder",
      required = true
  )
  @JcrPath(
      pickerConfiguration = "cms-pickers/documents-folders-only",
      pickerSelectableNodeTypes = { "hippostd:folder" },
      isRelative = true
  )
  String getContentFolder();
}

In the component, I retrieve the list of documents from the selected folder and pass it on to the template:

@ParametersInfo(
    type = FolderPickerComponentInfo.class
)
public class FolderPickerComponent extends CommonComponent {

  @Override
  public void doBeforeRender(HstRequest request, HstResponse response) {
    super.doBeforeRender(request, response);

    FolderPickerComponentInfo paramInfo = getComponentParametersInfo(request);
    List<HippoDocumentBean> contentDocuments = Collections.emptyList();

    String folderPath = paramInfo.getContentFolder();
    if (folderPath != null) {
      HippoFolder folder = getHippoBeanForPath(folderPath, HippoFolder.class);
      if (folder != null) {
        contentDocuments = folder.getDocuments();
      }
    }

    request.setAttribute("contentDocuments", contentDocuments);
  }
}

In the template, I can then render any information about these documents:

<#include "../include/imports.ftl">

<#-- @ftlvariable name="contentDocuments" type="java.util.List<org.hippoecm.hst.content.beans.standard.HippoDocumentBean>" -->

<#list contentDocuments>
  <ul>
    <#items as content>
      <li>${content.displayName}</li>
    </#items>
  </ul>
<#else>
  <p>No documents</p>
</#list>

After registering the template in /hst:hst/hst:configurations/hippofolderpicker/hst:templates:

/folder-picker:
  jcr:primaryType: hst:template
  hst:renderpath: webfile:/freemarker/hippofolderpicker/folder-picker.ftl

And the component in /hst:hst/hst:configurations/hippofolderpicker/hst:catalog:

/folder-picker:
  jcr:primaryType: hst:containeritemcomponent
  hst:componentclassname: com.damirscorner.blog.samples.components.FolderPickerComponent
  hst:label: Folder Picker
  hst:template: folder-picker
  hst:xtype: item

The newly crested component appears in the Channel Editor where it can be added to a page and configured using the built-in content picker:

FolderPicker component in Hippo Channel Editor

The functionality wasn't difficult to implement. It just took longer than necessary because of incomplete documentation. That's something that happens too often when working with Hippo CMS.

Copyright
Creative Commons License