# How do I set up a TreeComponent?

This how-to describes how to set up a com.cm4ap.base.tree.tree-component using the example of the contact module. A TreeComponent is to be set up, which visualizes the hierarchy of contacts. The TreeComponent is to be displayed in the main view of the contact module below the search renderer.

# Requirements

The only prerequisite for a functioning 'TreeComponent' is a CoreEngine module that stores its records in a tree structure and does this with the help of the 'CoreEngine' field 'pid'. For setup, see `tree_structure'.

# Configuration

The next step describes the establishment of the TreeComponent step by step.

# 1. TreeComponent

First, the TreeComponent itself is required. To do this, a new component is created in the target layout at the desired position in the elements area:

<!-- TreeComponent -->
<component id="treeComponent" component="cm4ap-tree-component">
</component>

Up to now, nothing can be seen in the frontend, because the TreeComponent does not yet know which data it should display.

# 2. TreeItemRenderer

For this purpose, an ItemRenderer must be specified, which represents the individual data records (in this example contacts). First, a com.cm4ap.base.tree.tree-item-renderer is used. For this purpose, a components.lists.list-item-renderer-factory must be created, which creates an ItemRenderer for each record:

<!-- Item Renderer Factory -->
<actor id="treeItemRendererFactory" type="ListItemRendererFactory">
    <parameter>
        <entry key="itemRenderer">com.cm4ap.base.tree.TreeItemRenderer</entry>
    </parameter>
</actor>

The actor must also be assigned to the TreeComponent:

<!-- TreeComponent -->
<component id="test" component="cm4ap-tree-component">
    <parameter>
        <entry key="itemRenderer" class="actor">treeItemRendererFactory</entry>
    </parameter>
</component>

# 3. TreeActor

In order for the TreeComponent to display the desired data, a com.cm4ap.base.tree.tree-actor must be created. The TreeActor can be used to control which data is displayed:

<!-- TreeActor -->
<actor id="treeActor" type="CEPidTreeActor">
    <parameter>
        <entry key="module">contact</entry>
    </parameter>
</actor>

The TreeActor gets the Module-Name from the passed parameters. Now the TreeComponent and TreeActor must be linked. Therefor the TreeComponent gets the TreeActor from the passed parameters.

<!-- TreeComponent -->
<component id="test" component="cm4ap-tree-component">
    <parameter>
        <entry key="itemRenderer" class="actor">treeItemRendererFactory</entry>
        <entry key="listActor" class="actor">treeActor</entry>
    </parameter>
</component>

If now a reload of the CoreEngine is executed, the TreeComponent should be visible in the Main-View. And the friendlynames of the contacts should be displayed.

# 4. Assign data hierarchically

Currently, the data is most likely not yet arranged hierarchically, so the contacts in the TreeComponent are simply a list.

To arrange data hierarchically, another field renderer can now be added in the detail view. The "superior" of a contact can be selected via this:

<field_renderer>
    <type>Reference</type>
    <field>
        <name>pid</name>
    </field>
</field_renderer>

The contacts should now be displayed hierarchically.

# 5. Linien

In the TreeComponent, connecting lines between parent and child elements could be displayed. For this the TreeComponent gets the the value showLines from the parameter:

<!-- TreeComponent -->
<component id="treeComponent" component="cm4ap-tree-component">
    <parameter>
        <entry key="itemRenderer" class="actor">treeItemRendererFactory</entry>
        <entry key="listActor" class="actor">treeActor</entry>
        <entry key="showLines" class="boolean">true</entry>
    </parameter>
</component>

# 6. BaseBeanTreeItemRenderer

With the com.com4ap.ce.global.tree.base-bean-tree-item-renderer you can use a specialized ItemRenderer for displaying the individual BaseBeans.

<!-- Item Renderer Factory -->
<actor id="treeItemRendererFactory" type="ListItemRendererFactory">
    <parameter>
        <entry key="itemRenderer">cm4ap-base-bean-tree-item-renderer</entry>
    </parameter>
</actor>

The BaseBeanTreeItemRenderer can:

  • Display the object image of the base bean
  • Show any icon instead of the object image
  • Show a button to execute the conditional operations of the bean
  • Show a checkbox

Because the ItemRenderer isn't included as a Component but as a components.lists.list-item-renderer-factory in the layout, the parameters for the ItemRenderer have to be passed to the parameters for the ListItemRendererFactory

# 6.1 Object-Image

The object image can be switched on via the 'showObjectImage' parameter:

<!-- Item Renderer Factory -->
<actor id="treeItemRendererFactory" type="ListItemRendererFactory">
    <parameter>
        <entry key="itemRenderer">cm4ap-base-bean-tree-item-renderer</entry>
        <entry key="itemRendererProperties" class="map">
            <entry key="showObjectImage" class="boolean">true</entry>
        </entry>
    </parameter>
</actor>

# 6.2 Object-Icon

As an alternative to the object image, an icon can be displayed for each BaseBean. For this purpose the parameter iconName is set:

<!-- Item Renderer Factory -->
<actor id="treeItemRendererFactory" type="ListItemRendererFactory">
    <parameter>
        <entry key="itemRenderer">cm4ap-base-bean-tree-item-renderer</entry>
        <entry key="itemRendererProperties" class="map">
            <entry key="iconName">M-CONTACT</entry>
        </entry>
    </parameter>
</actor>

# 6.3 Object-Icon mit zusätzlichen Icons

In addition to the object icon, up to four further icons can be displayed on the object icon. These icons are displayed whenever the value of an assigned CEBoolean field of the current record is set to true.

In the following example a field external_sales was created in the CoreEngine module contact. This field should indicate if the contact is a sales representative. If this is the case, the icon M-FAVORITE_OBJ should be displayed on the object icon.

<!-- Item Renderer Factory -->
<actor id="treeItemRendererFactory" type="ListItemRendererFactory">
  <parameter>
     <entry key="itemRenderer">cm4ap-base-bean-tree-item-renderer</entry>
     <entry key="itemRendererProperties" class="map">
        <entry key="iconName">M-CONTACT</entry>
        <entry class="map" key="icons">
           <entry class="string" key="external_sales">M-FAVORITE_OBJ</entry>
        </entry>
     </entry>
  </parameter>
</actor>

For performance reasons, in addition to the specification in the ListItemRendererFactory in the TreeActor, the additionalFields parameter must be used to specify which fields should be loaded additionally. Thus, not every ItemRenderer with an additional backend request has to do this itself, but the TreeActor, which is responsible for loading the data, can load the required data directly:

<!-- TreeActor -->
<actor id="treeActor" type="CEPidTreeActor">
    <parameter>
        <entry key="module">contact</entry>
        <entry key="additionalFields" class="array">
            <value>external_sales</value>
        </entry>
    </parameter>
</actor>

# 6.4 Conditional Operations

On each BaseBeanTreeItemRenderer there is a button that can be used to call the conditional operation menu. All conditional operations of the main view are available there. The button can be shown or hidden using the parameter showCOButton. The button is visible by default. With the value 'false' it is hidden:

<!-- Item Renderer Factory -->
<actor id="treeItemRendererFactory" type="ListItemRendererFactory">
<parameter>
    <entry key="itemRenderer">cm4ap-base-bean-tree-item-renderer</entry>
    <entry key="itemRendererProperties" class="map">
        <entry key="showObjectImage" class="boolean">false</entry>
        <entry key="iconName">M-CONTACT</entry>
        <entry class="map" key="icons">
           <entry class="string" key="external_sales">M-FAVORITE_OBJ</entry>
        </entry>
        <entry key="showCOButton" class="boolean">false</entry>
    </entry>
</parameter>
</actor>

# 7. Markierungen und Suchen

The user can influence search results via the TreeComponent by means of some additional actuators. The goal in this example is to adjust the search results of the search renderers of the main view of the contact module so that only the selected contacts and their direct subordinates are displayed.

To do this, a components.lists.selection-actor must first be configured. This actor is the one who makes sure that the individual data records can be selected:

<!-- SelectionActor -->
<actor id="selectionActor" type="SelectionActor">
    <parameter>
        <entry key="multiple">true</entry>
        <entry key="markable">true</entry>
        <entry key="selectable">true</entry>
    </parameter>
</actor>

The SelectionActor must now be assigned to the TreeComponent:

<!-- TreeComponent -->
<component id="treeComponent" component="cm4ap-tree-component">
    <parameter>
        <entry key="itemRenderer" class="actor">treeItemRendererFactory</entry>
        <entry key="listActor" class="actor">treeActor</entry>
        <entry key="selectionActor" class="actor">selectionActor</entry>
        <entry key="showLines" class="boolean">true</entry>
    </parameter>
</component>

Now the data records can be selected. On the other hand, there is now the already existing construct that ensures that a search result with contacts is displayed. The TreeComponent and the search result (more precisely: the components.layout.search.search-actor) now have to be connected. For this there is the actor components.lists.selection-search-actor. It receives the SelectionActor with the currently marked contacts and the SearchActor':

<!-- SelectionSearchActor -->
<actor id="selectionSearchActor" type="SelectionSearchActor">
    <parameter>
        <entry key="itemRenderer" class="actor">treeItemRendererFactory</entry>
        <entry key="selectionActor" class="actor">selectionActor</entry>
        <entry key="searchActor" class="actor">mainSearchActor</entry>
        <entry key="searchFilterTemplates" class="array">
            <value class="map">
                <!-- operator muss für den ersten Filter nicht angegeben werden -->
                <entry key="field">id</entry>
                <entry key="comparator">=</entry>
                <entry key="valueField">id</entry>
            </value>
            <value class="map">
                <entry key="operator">or</entry>
                <entry key="field">pid</entry>
                <entry key="comparator">=</entry>
                <entry key="valueField">id</entry>
            </value>
        </entry>
    </parameter>
</actor>

The most important parameter for this actor is the searchFilterTemplates parameter. It describes the search filters to be generated. They are created for each record that is selected and gets linked with or.

The first filter restricts the search to all contacts whose id field matches the id field of a selected record. More simply, it allows records that have been selected in the TreeComponent to be included in the search result.

The second search filter allows search results whose pid field corresponds to an id field of the selected contacts. This search filter will find all contacts whose "superiors" are marked in the TreeComponent.

For the first search filter-template no operator has to be specified, because the search filters for each BaseBean will linked by or anyway.

Request missing documentation