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 demo/plugin/src/main/resources/hcm-config/main.yaml in the taxonomy-demo project. This configuration is injected in order to replace the default taxonomy editor plugin.
definitions: config: /hippo:namespaces/hippotaxonomy/taxonomy/editor:templates/_default_/root: plugin.class: org.onehippo.taxonomy.demo.plugin.AdditionalFieldCustomTaxonomyEditorPlugin
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 demo/plugin/src/main/resources/hcm-config/main.yaml in the taxonomy-demo project. This configuration is injected into /hippo:namespaces/taxonomydemo/textpage/editor:templates/_default_ configuration node, in order to replace the default taxonomy picker plugin.
definitions: config: /hippo:namespaces/taxonomydemo/canontextpage/editor:templates/_default_/taxonomy: plugin.class: org.onehippo.taxonomy.demo.plugin.AdditionalFieldCustomTaxonomyPickerPlugin
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.
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.