# PID Tree Layout Configuration

A PID (parent ID) tree is a hierarchical tree structure. It visualizes the objects of a module and the relationships between them. A PID tree also allows to include a self-reference in the database's module table.
In the default, DAM module "Folder" is displayed as a tree structure in the sidebar of module "Files":

A PID tree structure can be configured for each module. The prerequisite for the creation and display of a tree structure is to enable the PID tree functionality in a module's module configurations. After that, the tree structure of a module can be added to a layout. Here you can also make further configurations, like adding actions or enabling a drag and drop functionality.

# Activate PID for a Module

To activate the PID tree functionality for a module, just follow these steps:

  1. Go to admin snap-in Module configurations/{module}/Module definition.
  2. Set field "Enable hierarchical tree structure" (enable_tree_structure) to true.
  3. Save your setting and reload/restart the system.

After reload/restart, new fields pid and pid_path are automatically created in the module table of the database. As soon as they are part of a module table, default system hooks that consider these fields will apply for this module, too.
In addition to the field itself, a non-unique index is created on field pid.

You can now configure your layout to display the tree structure.

# Display and Configure Tree Structure

To display a module's tree structure in the GUI, you need to make a layout change in your target layout and add the pid_tree layout.
Optionally, you can configure the tree structure as a search filter and/or enable dropping objects from other modules in the same change.

As an example, we want to display module category (Product Categories) as a tree structure in module product (Products), and also enable the search filter and the external drag and drop functionalities:

# Add pid_tree Layout

First you need to add the pid_layout to your target layout. The default pid_layout is stored in folder global/defaults/layouts/pid_tree and needs to be imported via a layout change. This change will add the tree structure of the defined module and in it, all actions that are enabled/visible for view "pid_tree" (action details).

In our example, we add the pid_layout to the main layout of module product:

<change xpath="//component[@id='leftBar']/children" type="add">
  <import_layout layout_id="pid_tree" module="category">
    <parameter>
      <entry class="string" key="displayField">name</entry>
    </parameter>
  </import_layout>
</change>

As a result, the sidebar of module "Products" will look like this:

# Customize Default Layout

If required, you can customize the settings of default layout pid_tree. From it, you may change the following:

  • the given parameters from tag <consts>
  • the involved actors' parameters
  • parameter minLiveSearchLength to change the minimum number of characters required to start the live search (default: 3)

Remove Search Bar

If you want to remove the default search bar completely, you can only do so by changing the layout:

<change xpath="//component[@id='treeSearch']" type="remove"/>

Further Documentation: Layout changes

# PID Tree Specific Actions

For the tree structure objects, several actions are available. Some actions are pid_tree specific and can only be performed in a tree (e.g. "Create parent object"). Apart from that, each action will appear in the "More" button menu next to an object, as soon as it is set to visible=true for view pid_tree:

<views>
    <view visible="true">pid_tree</view>
</views>

Default Core Engine pid_tree actions are:

Name Enabled/Visible in Menu Description
pid_tree-create_parent enabled by default
visible *
allows users to create a parent object for the selected object
pid_tree-create_child enabled by default
visible *
allows users to create a child object for the selected object
pid_tree-rename enabled by default
visible *
allows to rename the selected object (field name)
pid_tree-delete_recursively enabled by default
visible
allows users to delete a complete branch (including all its child elements)
pid_tree-link_internal enabled by default
not visible
allows to drop elements from the tree on other objects of the tree
pid_tree-link_external disabled by default
not visible
allows to drop elements from other modules on objects of the tree

* This action is only available, if displayField is set to name or another field but friendlyname. For friendlyname, this action does not work and will not be available in the tree.

# Configure Tree Structure as Search Filter

With the following change, you can add the actors required to display the contents of selected PID objects as a search result in the main view.

In our example, we want to display only products that are within the selected categories. The required search field is thus category:

    <change xpath="//actors" type="add">
        <actor id="CategoryTreeRelatedSelectionSearchActor" type="RelatedPidSelectionSearchActor">
          <parameter>
            <entry class="string" key="pidSearchField">category</entry> 
            <entry class="string" key="pidPathSearchField">category.pid_path</entry> 
            <entry class="actor" key="searchActor">mainSearchActor</entry>
            <entry class="actor" key="selectionActor">CategoryTreeSelectionActor</entry>
          </parameter>
        </actor>
        <actor id="CategoryTreeSelectionActor" type="SelectionActor">
          <parameter>
            <entry class="boolean" key="multiple">true</entry>
            <entry class="boolean" key="markable">true</entry>
          </parameter>
        </actor>
    </change>

Additionally, both selectionActor and pidSelectionSearchActor need to be defined in the import_layout change:

    <import_layout layout_id="pid_tree" module="category">
      <parameter>
        <entry class="actor" key="selectionActor">CategoryTreeSelectionActor</entry>
        <entry class="actor" key="pidSelectionSearchActor">CategoryTreeRelatedSelectionSearchActor</entry>
        <entry class="string" key="displayField">name</entry>
      </parameter>
    </import_layout>

# Configure Drag and Drop

For each PID tree in a layout, the drag and drop functionality can be enabled. With it, you can drop objects into the tree's objects. A distinction is made between internal and external dropping:

  • With internal dropping you can move and drop elements within the tree. This function is controlled via action pid_tree-link_internal and is enabled by default.
  • With external dropping you can drop elements from outside the tree (i.e., another module) and thus create a relation. This function is controlled via action pid_tree-link_external and requires extra configuration.

To enable and configure drag and drop, further layout changes in the target layout are required. The following changes bring the following functionalities:

  • First change:
    1. enable dragging objects of the tree (first map: "drag")
    2. enable internal dropping of categories in the "Category" tree (second map: "drop", first value)
    3. enable external dropping of products in the "Category" tree using field "category" from module "Products" (second map: "drop", second value)
  • Second change:
    1. enable dragging objects from module "Products"
  • Third change:
    1. apply drag options to all item renderer factories in search result (one for each view type: "tile", "grid", "list")

Please note: Dragging as well as internal dropping are modifications of default layout pid_tree. Only the external dropping is not part of the default layout and must always be added.

    <change xpath="//actors" type="add">
        <!-- Enable dragging -->
        <actor id="CategoryTreeDragAndDropOptions" type="DragAndDropOptions">
          <parameter>
            <entry class="map" key="drag">
              <entry class="boolean" key="enabled">true</entry>
              <entry class="boolean" key="showObjectImage">false</entry>
              <entry class="boolean" key="showLabel">true</entry>
            </entry>
        <!-- Internal dropping -->
            <entry class="array" key="drop">
              <value class="map">
                <entry class="string" key="moduleName">category</entry>
                <entry class="boolean" key="preventSelf">true</entry>
                <entry class="boolean" key="preventCircularReference">true</entry>
                <entry class="string" key="actionName">pid_tree-link_internal</entry>
                <entry class="string" key="modifier">NONE</entry>
              </value>
        <!-- External dropping from another module -->
              <value class="map">
                <entry class="string" key="moduleName">product</entry>
                <entry class="string" key="relationFieldName">category</entry>
                <entry class="boolean" key="isFieldInTarget">false</entry>
                <entry class="string" key="actionName">pid_tree-link_external</entry>
                <entry class="string" key="modifier">NONE</entry>
              </value>
            </entry>
          </parameter>
        </actor>
    </change>

    <change xpath="//actors" type="add">
        <actor id="ProductsDragAndDropOptions" type="DragAndDropOptions">
          <parameter>
            <entry class="map" key="drag">
              <entry class="boolean" key="enabled">true</entry>
              <entry class="boolean" key="showObjectImage">false</entry>
              <entry class="boolean" key="showLabel">true</entry>
            </entry>
          </parameter>
        </actor>
    </change>

    <change xpath="//actor[@type='SearchFactory']/parameter" type="add">
        <entry class="map" key="itemRendererProperties">
          <entry class="actor" key="dragAndDropOptions">ProductsDragAndDropOptions</entry>
        </entry>
    </change>

# Full Layout Example

In the XML example, all configurations described above apply. If you want to add this to a layout, make sure to replace the target/source module names and field names as well as the actor IDs.
This layout change should work out of the box in any standard main view.

<changes>
  
  <!-- Import pid_tree layout -->
  <change xpath="//component[@id='leftBar']/children" type="add">
    <import_layout layout_id="pid_tree" module="category">
      <parameter>
        <entry class="actor" key="selectionActor">CategoryTreeSelectionActor</entry>
        <entry class="actor" key="pidSelectionSearchActor">CategoryTreeRelatedSelectionSearchActor</entry>
        <entry class="string" key="displayField">name</entry>
        <entry class="actor" key="dragAndDropOptions">CategoryTreeDragAndDropOptions</entry>
      </parameter>
    </import_layout>
  </change>
  <!-- Search Filter -->
  <change xpath="//actors" type="add">
    <actor id="CategoryTreeRelatedSelectionSearchActor" type="RelatedPidSelectionSearchActor">
      <parameter>
        <entry class="string" key="pidSearchField">category</entry>
        <entry class="string" key="pidPathSearchField">category.pid_path</entry>
        <entry class="actor" key="searchActor">mainSearchActor</entry>
        <entry class="actor" key="selectionActor">CategoryTreeSelectionActor</entry>
      </parameter>
    </actor>
    <actor id="CategoryTreeSelectionActor" type="SelectionActor">
      <parameter>
        <entry class="boolean" key="multiple">true</entry>
        <entry class="boolean" key="markable">true</entry>
      </parameter>
    </actor>
  </change>
  <!-- Drag and Drop -->
  <change xpath="//actors" type="add">
    <actor id="CategoryTreeDragAndDropOptions" type="DragAndDropOptions">
      <parameter>
        <entry class="map" key="drag">
          <entry class="boolean" key="enabled">true</entry>
          <entry class="boolean" key="showObjectImage">false</entry>
          <entry class="boolean" key="showLabel">true</entry>
        </entry>
        <entry class="array" key="drop">
          <value class="map">
            <entry class="string" key="moduleName">category</entry>
            <entry class="boolean" key="preventSelf">true</entry>
            <entry class="boolean" key="preventCircularReference">true</entry>
            <entry class="string" key="actionName">pid_tree-link_internal</entry>
            <entry class="string" key="modifier">NONE</entry>
          </value>
          <value class="map">
            <entry class="string" key="moduleName">product</entry>
            <entry class="string" key="relationFieldName">category</entry>
            <entry class="boolean" key="isFieldInTarget">false</entry>
            <entry class="string" key="actionName">pid_tree-link_external</entry>
            <entry class="string" key="modifier">NONE</entry>
          </value>
        </entry>
      </parameter>
    </actor>
  </change>
  <change xpath="//actors" type="add">
    <actor id="ProductsDragAndDropOptions" type="DragAndDropOptions">
      <parameter>
        <entry class="map" key="drag">
          <entry class="boolean" key="enabled">true</entry>
          <entry class="boolean" key="showObjectImage">false</entry>
          <entry class="boolean" key="showLabel">true</entry>
        </entry>
      </parameter>
    </actor>
  </change>
  <change xpath="//actor[@type='SearchFactory']/parameter" type="add">
    <entry class="map" key="itemRendererProperties">
      <entry class="actor" key="dragAndDropOptions">ProductsDragAndDropOptions</entry>
    </entry>
  </change>

</changes>
Request missing documentation