Taxonomy Plugin Category Detail View/Editor Customization - BloomReach Experience - Open Source CMS

This article covers a Hippo CMS version 11. There's an updated version available that covers our most recent release.

04-07-2016

Taxonomy Plugin Category Detail View/Editor Customization

Taxonomy Category Detail View/Editor Customization

In case you want to customize the taxonomy category info and its UI for specific requirements, you might want to consider extending the existing plugin classes and overriding some methods. Suppose you want to store additional fields such as 'Full Description' in each category node and allow users to view/edit the category detail with the additional fields. In order to fulfill this kind of customization requirements, the plugin Java classes are carefully designed and implemented so that you can replace the plugin configuration with your custom classes, which extend/override the plugin classes.

Full Description Custom Field Example in the Demo Project

In the Taxonomy Plugin Demo project, you can find a customization example which customizes the existing plugin classes in order to add 'full description' property in each localized category info node and allow viewing/editing the additional fields.

The customized Taxonomy Plugin example code and configuration is located in the plugin module project, the artifactId of which is taxonomy-addon-demo-plugin, under the taxonomy-demo project.

By default, the cms module project has a dependency on the taxonomy-addon-demo-plugin project. The customized plugin code is activated in the CMS through this dependency, because the module injects configuration into the repository at bootstrap time). If you want to run the CMS without this customized code, you can simply comment out the following dependency in the pom.xml of the cms module of the taxonomy-demo project.

    <!--
      The Customized Taxonomy Plugins and Configurations.
      If you don't want to use this customized plugins,
      please comment out the following dependency.
    -->
    <dependency>
      <groupId>org.onehippo.forge</groupId>
      <artifactId>taxonomy-addon-demo-plugin</artifactId>
      <version>${project.version}</version>
    </dependency>

If you run the taxonomy-demo project, you see the following screen when editing the taxonomy document in the CMS. In addition to the default taxonomy editor plugin, you see the 'Full Description' field. This customized taxonomy editor plugin allows users to specify a 'Full Description' for each category. This information is stored in the child localized nodes of the category node.

Also, if you edit a document in the CMS and try to add a taxonomy into the document, then you see the customized taxonomy picker dialog, like in the following screenshot. As you are able to edit an additional 'Full Description' field in the custom taxonomy editor plugin, you can see the field in the Category details panel on the right.

Now, let's look into the configuration and custom code in detail.

Custom Taxonomy Editor Plugin Class

The following configuration is found in plugin/src/main/resources/hippoecm-extension.xml in the taxonomy-demo project. This configuration is injected in order to replace the default taxonomy editor plugin.

<sv:node sv:name="canontextpage-custom-taxonomy-field">
    <sv:property sv:name="jcr:primaryType" sv:type="Name">
      <sv:value>hippo:initializeitem</sv:value>
    </sv:property>
    <sv:property sv:name="hippo:sequence" sv:type="Double">
      <sv:value>30251.1</sv:value>
    </sv:property>
    <sv:property sv:name="hippo:contentroot" sv:type="String">
      <sv:value>/hippo:namespaces/taxonomydemo/canontextpage/editor:templates/_default_/taxonomy/plugin.class</sv:value>
    </sv:property>
    <sv:property sv:name="hippo:contentpropset" sv:type="String">
      <sv:value>org.onehippo.taxonomy.demo.plugin.AdditionalFieldCustomTaxonomyPickerPlugin</sv:value>
    </sv:property>
  </sv:node>

The source of the custom taxonomy editor plugin is like the following:

/**
 * AdditionalFieldCustomTaxonomyEditorPlugin
 * <P>
 * This extended plugin is an example to show how you can add a custom field
 * in the category editing page.
 * So, this extended plugin adds 'fulldescription' field in addition to the
 * 'description' field.
 * </P>
 * @version $Id$
 */
public class AdditionalFieldCustomTaxonomyEditorPlugin extends TaxonomyEditorPlugin {

    private static final long serialVersionUID = 1L;

    private final class FullDescriptionModel implements IModel<String> {
        private static final long serialVersionUID = 1L;

        public String getObject() {
            EditableCategory category = getCategory();

            if (category != null) {
                return category.getInfo(getCurrentLanguageSelection().getLanguageCode()).getString(CustomTaxonomyConstants.FULL_DESCRIPTION, "");
            }

            return null;
        }

        public void setObject(String object) {
            EditableCategoryInfo info = getCategory().getInfo(getCurrentLanguageSelection().getLanguageCode());

            try {
                info.setString(CustomTaxonomyConstants.FULL_DESCRIPTION, object);
            } catch (TaxonomyException e) {
                error(e.getMessage());
                redraw();
            }
        }

        public void detach() {
        }
    }

    public AdditionalFieldCustomTaxonomyEditorPlugin(IPluginContext context, IPluginConfig config) {
        super(context, config);

        final boolean editing = "edit".equals(config.getString("mode"));
        final Form container = getContainerForm();

        if (editing) {
            container.add(new TextAreaWidget("fulldescription", new FullDescriptionModel()));
        } else {
            container.add(new MultiLineLabel("fulldescription", new FullDescriptionModel()));
        }
    }

}

The customization code simply extends the default TaxonomyEditorPlugin class and overrides the constructor to add a new UI component for the full description field. The other code lines are just for providing a model object for the new full description field and they are just copied from the description model of the base class.

Since the parent class, TaxonomyEditorPlugin, has an HTML markup template containig <wicket:child />, the child class such as AdditionalFieldCustomTaxonomyEditorPlugin can have additional UI components in its HTML markup template to extend the parent's markup HTML template.

Here's the HTML markup snippet of the TaxonomyEditorPlugin template:

            <tr>
              <td><wicket:message key="description" />:</td>
              <td class="hippo-editor-field">
                <!-- SNIP -->
              </td>
            </tr>
            <wicket:child />
            <tr>
              <td><wicket:message key="synonyms" />:</td>
              <!-- SNIP -->
          

And, here's the HTML markup snippet of the AdditionalFieldCustomTaxonomyEditorPlugin template:

<html xmlns:wicket="http://wicket.apache.org/">
<wicket:extend>
  <tr>
    <td><wicket:message key="fulldescription" />:</td>
    <td class="hippo-editor-field">
      <div class="hippo-editor-field-subfield even">
        <div class="hippo-editor-field-subfield-item">
          <div class="hippo-editor-field-value">
            <div class="hippo-editor-field-value-container" wicket:id="fulldescription">[ full description ]</div>
          </div>
        </div>
      </div>
    </td>
  </tr>
</wicket:extend>
</html>

A child class extending TaxonomyEditorPlugin class can extend HTML markups as shown above. In this way, you can add some extra fields in your custom Taxonomy Editor Plugin class by using the markup inheritance feature of Apache Wicket. See  Creating layouts using markup inheritance for detail.

In the above example, the constructor just creates and adds a UI component for the full description field. As the base class does for the description field, it adds an editable field when in edit mode. Otherwise, it adds a multi-line label instead.

For this kind of UI customization purpose, the base class provides protected methods for the child classes, such as #getContainerForm() with which you can get access to the form UI container of the category detail pane. Please see the JavaDocs API Documentation for detail.

Custom Taxonomy Picker Class

We also need to customize the taxonomy picker plugin which pops up when selecting taxonomy categories in a document.

The following configuration is found in plugin/src/main/resources/textpage-custom-taxonomy-field.xml in the taxonomy-demo project. This configuration is injected through hippoecm-extension.xml into /hippo:namespaces/taxonomydemo/textpage/editor:templates/_default_ configuration node, in order to replace the default taxonomy picker plugin.

<?xml version="1.0" encoding="UTF-8"?>
<sv:node
    xmlns:sv="http://www.jcp.org/jcr/sv/1.0"
    xmlns:h="http://www.onehippo.org/jcr/xmlimport"
    sv:name="taxonomy"
    h:merge="combine">
  <sv:property sv:name="jcr:primaryType" sv:type="Name">
    <sv:value>frontend:plugin</sv:value>
  </sv:property>
  <sv:property sv:name="plugin.class" sv:type="String">
    <sv:value>org.onehippo.taxonomy.demo.plugin.AdditionalFieldCustomTaxonomyPickerPlugin</sv:value>
  </sv:property>
</sv:node>

The code for the custom taxonomy picker plugin is:

public class AdditionalFieldCustomTaxonomyPickerPlugin extends TaxonomyPickerPlugin {

    private static final long serialVersionUID = 1L;

    public AdditionalFieldCustomTaxonomyPickerPlugin(IPluginContext context, IPluginConfig config) {
        super(context, config);
    }

    @Override
    protected AbstractDialog<Classification> createPickerDialog(ClassificationModel model, String preferredLocale) {
        return new AdditionalFieldCustomTaxonomyPickerDialog(getPluginContext(), getPluginConfig(), model, preferredLocale);
    }


}

The customization code simply extends the default TaxonomyPickerPlugin class and overrides the #createPickerDialog(...) method to create a custom dialog class, which also overrides the #addCategoryDetailFields(...) method in order to add a multi-line label for the full description field.

For this kind of UI customizations, the base classes provide protected methods for the child classes, such as #createPickerDialog(...) and #addCategoryDetailFields(...) with which you can customize the dialog and add additional UI components into the category detail pane. Please see the JavaDocs API Documentation for more details.

Note: Since the plugin is based on Apache Wicket Framework, you will need to customize the template HTML pages accordingly. See the Wicket Template Customization section below for detail.

Wicket Template Customization

Since CMS Plugins are Apache Wicket-based components, when you customize the UI of the plugin (e.g., adding a full description field in the detail pane), you have to add corresponding markup in the HTML templates and resource strings.

As shown above, you can use the markup inheritance feature of Apache Wicket where available. See Creating layouts using markup inheritance for detail.

You can find the customized taxonomy plugin HTML templates in the following source locations in the taxonomy-demo project:

  • plugin/src/main/resources/org/onehippo/taxonomy/plugin/*.html
  • plugin/src/main/resources/org/onehippo/taxonomy/plugin/*.properties

Also, you can find the original markup templates and resources in the taxonomy-addon-frontend-x.x.x.jar.

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?