Domain Bundles

Motivation

The previous sections show how different aspects of individual apps — such as the background maps, thematic layers, or search — can be configured.

However, there might be situations where many apps share the same configuration options, for example the same services for basemaps or thematical maps. Multiple apps can share parts of dedicated configuration options but not all of them.

With the help of domain bundles you can ship these configurations in a custom bundle. This bundle can be reused in multiple apps. In addition, multiple configuration options for various functionalities of an app can be combined into a single domain bundle. By this means all domain relevant configuration aspects can be delivered by one bundle.

The deployment as bundle helps to combine the configuration options contained in numerous apps in a various ways. Bundles also offer the option of being versioned. In this way, updates to the configuration of one or more apps can be distributed among multiple apps.

Create Domain Bundles

The configuration in a domain bundle is structured in the same way as in the app configuration file (app.json).

Structure and options

In general, a domain bundle contains at least one JSON file (manifest.json), which stores one or more configuration fragments. All configuration fragments are described in JSON within the keyword domain-config. You can configure one or more of these fragments in parallel in a domain bundle. The following code sample shows an empty configuration containing all allowed fragments:

{
    "name": "domain-yourCustomDomainBundleName",
    "version": "1.0.0",
    "dependencies": {
        "domains-system": "^4.4.0"
    },
    "main": "",
    "layer": "",
    "i18n": [],
    "domain-config": {
        "map-basemaps": [],
        "map-layers": [],
        "ags-stores": [],
        "report-mappings": []
    }
}

Each fragment is addressed by its own keyword. The configuration is similar to the corresponding part of the app configuration file (app.json). The following table lists the allowed fragments of the domain bundle configuration:

Fragment Keyword in domain-config Equivalent in app.json file

Basemaps

"map-basemaps"

"map-init": {
    "Config": {
        "basemaps": []
    }
}

Operational Layers

map-layers

"map-init": {
    "Config": {
        "map": {
            "layers": []
        }
    }
}

Sources for search and selection

ags-stores

"agssearch": {
  "AGSStore": []
}

Reports

report-mappings

"reporttool": {
  "ReportTask": {
    "mappings": []
  }
}

Complete sample

The following code sample shows a full domain bundle configuration using all available configuration fragments:

{
    "name": "domain-yourCustomDomainBundleName",
    "version": "1.0.0",
    "dependencies": {
        "domains-system": "^4.4.0"
    },
    "main": "",
    "layer": "",
    "i18n": [],
    "domain-config": {
        "map-basemaps": [
            {
                "id": "esri_street",
                "title": "Streets",
                "thumbnailUrl": "resource('images/thumbnailImage.png')",
                "basemap": "gray-vector"
            }
        ],
        "map-layers": [
            {
                "id": "koeln3",
                "title": "Koeln",
                "url": "https://services.conterra.de/arcgis/rest/services/common/koeln/MapServer",
                "coverImage": "resource('images/coverImage.png')",
                "type": "AGS_DYNAMIC",
                "visible": true
            }
        ],
        "ags-stores": [
            {
                "id": "store01",
                "title": "Adressen",
                "url": "https://services.conterra.de/arcgis/rest/services/common/koeln_adressen/MapServer/0",
                "searchAttribute": "ADRESSE",
                "searchLabel": "Adressen"
            }
        ],
        "report-mappings": [
            {
                "storeId": "store01",
                "reportId": "report01",
                "fileName": "Report.pdf"
            }
        ]
    }
}

Use Domain Bundles

Domain bundles are installed and used the same way as other bundles (see Managing bundles).

Domain bundles can be used in one or more apps. The configuration fragments of the domain bundles are added to the existing app configuration. Depending on the configuration fragment, the following general conditions apply.

Consequences for the app

Every fragment configured with a domain bundle (for example map or search) affects the app and its configuration. The following section describes how domain bundles affect app configurations:

Basemaps

Background maps are configured within the keyword map-basemaps in the same way as in app.json file. To define the active basemap, use the property "selected":true. For example:

{
    "map-basemaps": [
        {
            "id": "esri_street",
            "title": "Streets",
            "thumbnailUrl": "resource('images/thumbnailImage.png')",
            "basemap": "gray-vector",
            "selected": true
        }
    ]
}

The following table shows how background maps provided by domain bundles affect the app and its configuration:

Behavior when …​ Description Sample

…​ applying the configuration

Background maps from domain bundles are added to the app and are available for selection after loading the bundle.

Background maps with unique IDs are added to the map. Because only one background map can be selected, the background map is only selected from a domain bundle if there is no selected background map in the app and no other domain bundle has previously selected a background map.

…​ order is fixed

Background maps are added in the order of the loaded domain bundles.

In the map, only one background map is active at a time. However, the order has an effect on the display in the Basemap toggler, for example.

…​ a duplicate is found

Background maps that are already loaded are not overwritten. App configuration takes priority over domain bundle configuration.

The background map to be loaded is not applied if a background map that is already configured in the app or a background map that was previously loaded by another domain bundle has the same ID.

Operational Layer

The configuration of operational layers with the map-layers keyword in domain bundles corresponds to the configuration of the map.layers property in the map-init bundle configuration. For example:

{
    "map-layers": [
        {
            "id": "koeln3",
            "title": "Koeln",
            "url": "https://services.conterra.de/arcgis/rest/services/common/koeln/MapServer",
            "coverImage": "resource('images/coverImage.png')",
            "type": "AGS_DYNAMIC",
            "visible": true
        }
    ]
}

Operational layers from domain bundles are applied to the map in a similar way as if they were configured directly in the app. The following table presents situation-specific features:

Behavior when …​ Description Sample

…​ applying the configuration

Operational layers, sub-layers, popup templates and other configurations are added to the map as soon as the domain bundle is loaded.

…​ order is fixed

Operational layers are added to the map in a fixed order. All layers from domain bundles present at the app start are added as a block with the first loaded domain bundle on top and the last loaded at the bottom. Domain bundles activated afterwards are added at the bottom or top. Whether the operational layers are inserted before or after the layers already present in the app can be determined by configuration.

The order influences not only the arrangement of layers in the TOC, but also the display order - and overlapping - of layers in the map.

…​ a duplicate is found

Operational layers from a domain bundle with IDs that are already added to the map are not overwritten.

No configuration options of a layer whose ID already exists in the map are adopted - according to that, settings are not merged.

Override the domain bundle configuration of operational layers in apps

Within an app, you can override the default configuration defined in domain bundles for operational layers. The properties to be overridden are specified within map-layers-override for each layer. For example, this can be used to control the initial visibility of operational layers added by a domain bundle in the respective app:

Example - Overriding the configuration of an operational layer
"domains-system": {
    "Config": {
        "map-layers-override": {
            "trees": {
                "visible": false
            }
        }
    }
}

The IDs of the layers to be overridden are used as the keys of the map-layers-override object. In the preceding code sample the visibility of the layer with id trees is set to false.

You can also override properties of sub layers. Properties of sub layers can be overridden using the sublayers-override property as follows:

Example - Overriding a sub layer configuration
"domains-system": {
    "Config": {
        "map-layers-override": {
            "trees": {
                "sublayers-override": {
                    "1": {
                        "visible": false
                    }
                }
            }
        }
    }
}

Again, the IDs of sub layers to be overridden are used as the keys of the sublayers-override object.

Add operational layers on top or bottom of layers in the app.json file

By default, layers configured in domain bundles are inserted above the layers configured in the app.json file. To insert the layers from the domain bundles below those from the app configuration, set the following configuration:

Fragment from bundles section in app.json file
"domains-system": {
    "Config": {
        "domainLayersOnTop": true
    }
}

Stores for search and selection

Stores for search and spatial selection are configured with the keyword ags-stores - analogoue to the configuration of AGSStore for the agssearch bundle in app.json file.

To use this function the domain bundle needs to define a dependency to bundle agssearch. Alternatively, this bundle might be loaded in the app itself.

{
    "ags-stores": [
        {
            "id": "store01",
            "title": "Adressen",
            "url": "https://services.conterra.de/arcgis/rest/services/common/koeln_adressen/MapServer/0",
            "searchAttribute": "ADRESSE",
            "searchLabel": "Adressen"
        }
    ]
}
Behavior when …​ Description Sample

…​ applying the configuration

Stores from domain bundles are registered in the system and are available for various functions as defined in their useIn property.

A domain bundle can be used to expand the spatial selection and search by stores.

…​ order is fixed

The sequence has no effect on the functionality.

However, the loading order has implications on the source list of spatial selection.

…​ a duplicate is found

There is no check for duplicates or existing store.

Stores from a domain bundle with ID or URL that already exist are added to the app.

Report mappings

Report mappings are defined by keyword report-mapping - analogue to the ReportTask mappings of bundle reporttool in app.json file.

To use this function the domain-bundle needs to define a dependency to bundle reporttool. Alternatively, this bundle might be loaded in the app itself.

{
    "report-mappings": [
        {
            "storeId": "store01",
            "reportId": "report01",
            "fileName": "Report.pdf"
        }
    ]
}
Behavior when …​ Description Sample

…​ applying the configuration

Mappings from domain bundles are added in addition to existing mappings.

A domain-bundle can be used to provide custom mappings for its content.

…​ order is fixed

The sequence has no effect on the functionality.

In case of a duplicated definition of a mapping the mapping loaded first is used.

…​ a duplicate is found

The check is performed by property "storeId". If a mapping for a certain store is already defined the one that is loaded latest is ignored.

A mapping defined by a domain-bundle with a storeId that is already used by another mapping is not added to the app.

Evaluation order

As the preceding descriptions of the effects of domain bundles on app behavior show, the order in which domain bundles are loaded is crucial in many cases. You can adjust this order. Thus, for example, the display order of operational layers can be influenced. This also ensures that in case of ambiguous IDs, the particularly important domain bundles are loaded first.

The following code sample shows how to change the order in which domain bundles are loaded and applied. Specify the bundle names in the order in which they should be loaded. It is sufficient to specify only the bundle names for which a sequence is important. Bundles that are not listed are loaded and applied randomly after the performances.

Fragment from bundles section in app.json file
"domains-system": {
    "Config": {
        "domainBundleOrder": ["domain-domainBundleForBasmaps", "domain-domainBundleForMapLayers"]
    }
}
The order in which domain bundles are loaded is only evaluated when the app is starting. When dynamically starting or stopping a domain bundle during app runtime the order is ignored.