toc

This bundle provides a widget that displays the contents of the map in its hierarchical order. The visibility of this content can be controlled and certain actions can be performed for each element. Optionally, a legend for each layer can be displayed in the TOC and basemaps can be controlled.

Usage

To make the toc available to the user, add the tool ID tocToggleTool to a tool set.

This bundle contains a set of actions that can be run from an action menu of a layer, such as zooming to the extent of a layer or controlling its transparency. For a description of these actions and the conditions under which they are visible in the TOC, see provided actions. To add custom actions, see Use Cases.

For more details, see the API documentation.

Constraints

Legends for layers of type WMTSLayer (and their sublayers) and layer types not supported by the Legend widget cannot be displayed.

Configuration reference

The following code sample shows the configurable properties and their default values:

"Config": {
    "actions": ["*"],
    "showBasemaps": false,
    "showLayerLegend": false,
    "maxBasemapsThreshold": 3,
    "maxVisibleTitleLines": 3,
    "autoActivateParentLayer": true,
    "autoExpandLegend": false
}
Property Type Description
actions Array Defines which actions are available in the action menu. The order of actions in this array represents the order in the menu. The value [*] defines that all available actions are used, grouped by their layout type (button, slider, text-value). For details about the provided actions, see provided actions.
showBasemaps Boolean To show and control basemap, set this property to true.
showLayerLegend Boolean To show a legend for each layer or sublayer, set this property to true. If the corresponding layer is not visible, the legend is hidden.
maxBasemapsThreshold Number Maximum number of basemaps displayed in a flat list. If the number of basemaps is greater than the specified number, a dropdown is displayed.
maxVisibleTitleLines Number Number of text lines displayed for layer and service titles. If the titles are longer than this value, the texts are truncated.
autoActivateParentLayer Boolean By default, parent layers are activated automatically, when a child layer is activated. To keep the parent layer state unchanged, when a child layer is activated, set this property to false.
autoExpandLegend Boolean To automatically expand the layer legend when the layer is visible on the map and a legend is available, set this property to true.

Provided actions

The following code sample shows the actions provided by this bundle:

"Config": {
    "actions": [
        "show-description",
        "zoom-to-extent",
        "activate-children",
        "deactivate-children",
        "change-opacity",
        "show-copyright"
    ]
}

The visibility of an action is based on the available properties of the element referenced by the toc item, such as a layer or a group layer.

Name Visibility condition Description
zoom-to-extent The element has extent information with a valid value. The map is zoomed to this extent.
activate-children The element has at least one child. The visibility of the element and all children are set to true.
deactivate-children The element has at least one child. The visibility of the element and all children are set to false.
change-opacity The opacity value of the element can be changed. A slider is shown to change the layer's opacity.
show-description The element has a description property. The content of the description property is displayed in the menu. To show the content of the serviceDescription property, create a custom action.
show-copyright The element has a copyright property. The content of the copyright property is displayed in the menu.

Use cases

How to hide layers from the TOC

To hide a single layer from the toc, set the layer property listMode to hide. To hide the children of a layer but not the layer itself, set listMode to hide-children.

How to hide legends of certain layers

To hide the legend of a layer and all its children, set the layer property legendEnabled to false.

How to expand layers in toc widget

To expand a layer and show all its children in toc, set the layer property initiallyExpandedInToc to true.

How to customize basemap thumbnails

A thumbnail of the basemap is displayed before the name of each basemap. To customize this thumbnail, change the thumbnailUrl property of each basemap, as described in the map-init bundle documentation.

How to add a custom action

To add a custom action, provide a custom ActionDefinitionFactory. An ActionDefinition transports properties which depend on the chosen UI type and methods implementing the behavior.

The following UI types are provided:

UI type Description
button Action is shown as a button.
button-row Action is shown as multiple buttons in a row.
slider Action is shown as a slider.
text-label Action is shown as as a label.

Common structure of an ActionDefinitionFactory (custom action)

To create new action definitions, add components to the manifest.json file of your bundle, that implement the toc.ActionDefinitionFactory interface:

class MyCustomActionDefinitionFactory {

    constructor(){
        // which ids are recognized by this factory
        // important to support the ["*"] expression
        this.supportedIds = ["my-custom-id"];
    }

    // create a definition object
    createDefinitionById(id) {
        if(id !=="my-custom-id"){
            return;
        }
        return {
            // important to identify the ID of the created action
            id: "my-custom-id",
            // choose a ui type
            type: "button" | "slider" | "text-label",

            // other properties and methods depend on the selected ui type
            ...
        };
    }
}

An ActionDefinitionFactory has to be registered as toc.ActionDefinitionFactory:

{
    "components": [
        {
            "name": "MyCustomActionDefinitionFactory",
            "provides": "toc.ActionDefinitionFactory"
        }
    ]
}
Properties of a custom button action

The following shows a sample of a custom button action and all available options:

export default class MyCustomButtonActionDefinitionFactory {
    constructor() {
        this.supportedIds = ["my-button-action"];
    }
    createDefinitionById(id) {
        return {
            id,
            type: "button",

            // Label of the button menu entry
            label: "Do it",

            // Icon of the button entry
            icon: "search",

            // Method to decide if this action is available for a given tocItem
            isVisibleForItem(tocItem) {
                return true;
            },

            // method to decide if the action should be shown as disabled (optional)
            isDisabledForItem(tocItem) {
                return false;
            },

            // method triggered if the menu item is clicked
            trigger(tocItem) {
                // do some thing
            }
        };
    }
}
Properties of a custom button-row action

The following shows a sample of a custom button-row action and all available options:

export default class MyCustomButtonRowActionDefinitionFactory {
    constructor() {
        this.supportedIds = ["my-button-row-action"];
    }
    createDefinitionById(id) {
        return {
            id,
            type: "button-row",

            // Label of the button menu entry
            label: "Do it",

            // Icons for the buttons
            icons: ["action-1", "action-2"],
            // Label that is used as Aria-Label
            actionLabels: ["My Action Label 1", "My Action Label 2"],
            // optional tooltip. When not defined, the 'label' will be displayed as tooltip
            actionTooltips: ["tooltiptext-1", "tooltiptext-2"],
            // Method to decide if this action
            // is available for a given tocItem
            isVisibleForItem(tocItem) {
                return true;
            },

            // Method to decide if one of the buttons should be shown as
            // disabled (optional)
            // It is important that an array is returned
            // in matching order to the icons property.
            isDisabledForItem(tocItem) {
                return [true, false];
            },

            // Method triggered if the a button is clicked
            // The actionIndex identifies the target action
            trigger(tocItem, actionIndex) {
                // do something
            }
        };
    }
}
Properties of a custom slider action

The following shows a sample of a custom slider action and all available options:

export default class MyCustomSliderActionDefinitionFactory {
    constructor() {
        this.supportedIds = ["my-custom-slider"];
    }
    createDefinitionById(id) {
        return {
            id,
            type: "slider",

            // Label/title of the slider menu entry
            label: "Opacity",

            // Icon of the menu entry
            icon: "",

            // Label of the left side of the slider
            fromLabel: "",

            // Icon of the left side of the slider
            fromIcon: "",

            // Label of the right side of the slider
            toLabel: "",

            // Icon of the right side of the slider
            toIcon: "",

            // Minimum slider value (left side)
            min: 0,

            // Maximum slider value (right side)
            max: 1,

            // Increment value of the slider
            step: 0.01,

            // Method to decide if this action
            // is available for a given tocItem
            isVisibleForItem(tocItem) {
                return typeof tocItem.ref.opacity === "number";
            },

            // Method should return current value of the item
            valueOf(tocItem) {
                return tocItem.ref.opacity;
            },

            // Method is called by the slider if the value is changed
            changeValueOf(tocItem, val) {
                tocItem.ref.opacity = val;
            }
        };
    }
}
Properties of a custom text-label action

The following shows a sample of a custom text-label action and all available options:

export default class MyCustomTextActionDefinitionFactory {
    constructor(props) {
        this.supportedIds = ["my-custom-text"];
    }
    createDefinitionById(id) {
        return {
            id,
            type: "text-label",

            // Label/title of the slider menu entry
            label: "Copyright",

            // Icon of the menu entry
            icon: "copyright",

            // Label for the "show more" link
            labelMore: "..more",

            // Threshold that defines when to auto shorten the text and
            // provide a "show more" link instead.
            // If set to -1 text is never truncated.
            truncationThreshold: 200,

            // Method to decide if this action
            // is available for a given tocItem
            isVisibleForItem(tocItem) {
                return !!tocItem.ref.copyright;
            },

            // Method should return text value of the item
            valueOf(tocItem) {
                return tocItem.ref.copyright;
            },

            // Method which is called when the "show more" link is clicked
            // Only required if truncationThreshold is used
            trigger(tocItem) {
                // Do something (for example opening a window to show the whole text)
            }
        };
    }
}
Support for asynchronous behavior in actions

All action types have the method isVisibleForItem in common. This method is allowed to be asynchronous (return a Promise value).

The following sample of a custom asynchronous action (here of type text-label) shows the change:

export default class MyCustomAsyncActionDefinitionFactory {
    constructor(props) {
        this.supportedIds = ["my-custom-async"];
    }
    createDefinitionById(id) {
        return {
            id,

            type: "text-label",

            // Label/title of the slider menu entry
            label: "Async Action",

            // Method makes a request to decides asynchronously
            // if data is available for a given tocItem
            async isVisibleForItem(tocItem) {
                const data = await makeRequestForData(tocItem.ref);
                return !!data;
            },

            // Method should return text value of the item
            valueOf(tocItem) {
                // this must not return a promise!
                return requestedData.lookupInfoFor(tocItem.ref);
            }
        };
    }
}
Lifecycle of a custom action

An action is reused for multiple toc items, therefore it should not store any state or reference to a toc item. There are no lifecycle hooks available.

How to implement behavior in a custom action

The meta information about the current focused toc item is provided to the methods of a custom action. This information can be used to identify a layer in the map for example. See TocItem for more details.

How to enhance the reason messages why a layer is not yet visible

By default the toc checks the loaded state of a layer and the min/max scale requirements. If these requirements are not fulfilled, an icon is displayed that indicates why a service is not visible. These messages can be extended by implementing a custom toc.StateChecker.

class MyStateChecker {

    // This is called if the viewpoint of the map changes
    // or a layer is added/loaded
    checkState({ tocItem, mapWidgetModel }) {
        const visible = .... // check visibility
        if (visible){
          // nothing to do
          return;
        }

        // produce information about the reasons
        // decide what level of information you provide:
        return {
            // use infos for "info" level
            infos: ["my custom info"],
            // use warnings for "warning" level
            warnings: ["my custom warning"],
            // use errors for "errors" level
            errors: ["my custom error"],
        };

        // NOTE: you can return a promise
        return new Promise((resolve)=>{
            resolve({
              infos: ["my custom info"]
            });
        });
    }
}

The meta information about the current toc item is provided by the TocItem parameter. Information about the current map state can be resolved from the given mapWidgetModel.

A custom StateChecker has to be registered as toc.StateChecker:

{
    "components": [
        {
            "name": "MyStateChecker",
            "provides": "toc.StateChecker"
        }
    ]
}