Magnolia 5.7 reached extended end of life on May 31, 2022. Support for this branch is limited, see End-of-life policy. Please note that to cover the extra maintenance effort, this EEoL period is a paid extension in the life of the branch. Customers who opt for the extended maintenance will need a new license key to run future versions of Magnolia 5.7. If you have any questions or to subscribe to the extended maintenance, please get in touch with your local contact at Magnolia.
This page describes the Magnolia-specific directives !inherit
, !include
and !override
. You can use these directives to reuse configuration in YAML file-based configuration. !include
is supposed to be used when reusing an arbitrary resource, whereas !inherit
comes handy when extending a definition.
YAML include
Use !include
to add a reusable chunk. Include a YAML fragment on a sub-level of your new definition or include a complete YAML definition on top of your new definition. You can also modify the included part of the definition.
Reference the file you want to include by its resource path. The path to such a resource has the following pattern:
/<module-name>/path/to/the/reusable/chunk.yaml
.
If your !include
file is not working, check that the first line in the included YAML file does not have any indentation.
Syntactic variants of the directive
The !include
directive exists since Magnolia 5.4, which introduced configuration by YAML. With the release of 5.5.6, the directive's syntax has changed slightly. While the old syntax still works, the new one makes it possible to modify and override the included part of the definition. The new syntax uses a colon :
instead of the space
between !include
and the path to the resource.
Syntax | Requires version | Functions | |
---|---|---|---|
Deprecated syntax. | !include <path/to/a–ressource.yaml> | Magnolia 5.4+ | simple include |
New syntax. | !include:<path/to/a–ressource.yaml> | Magnolia 5.5.6+ | simple include, include and modify |
A generic recipe
- Prepare a fragment of definition which is suitable to be reused in many other item definitions.
- Include a resource with the
!include
directive. The included resource can contain a fragment or a complete definition. - Modify parts of the included definition.
Examples
Simple include
Include one tab in the form
and all the action definitions in the action
in a dialog definition. This example works with both the old (deprecated) and the new syntax.
Includable files:
name: tabCategories label: Categories fields: - name: categories label: Categories class: info.magnolia.ui.form.field.definition.MultiValueFieldDefinition label: Select category field: name: linkField class: info.magnolia.ui.form.field.definition.LinkFieldDefinition targetWorkspace: category appName: categories identifierToPathConverter: class: info.magnolia.ui.form.field.converter.BaseIdentifierToPathConverter - name: blackOrWhite label: Black or white class: info.magnolia.ui.form.field.definition.SelectFieldDefinition options: - name: black value: black selected: true label: Black - name: white value: white label: White
commit: class: info.magnolia.ui.admincentral.dialog.action.SaveDialogActionDefinition cancel: class: info.magnolia.ui.admincentral.dialog.action.CancelDialogActionDefinition
A dialog file which includes:
form: label: another-component tabs: - name: tabMain label: Main fields: - name: title label: Text class: info.magnolia.ui.form.field.definition.TextFieldDefinition label: Title # an include within a list, here adding a complete tab - !include:/module-a/includes/categorization-tab.yaml # an include within a map, here adding the actions for the root (map) item "actions" actions: !include:/module-a/includes/common-actions.yaml
Include and modify a fragment
Include one tab in the form
and all the action definitions in the action
in a dialog definition. This is similar as in the example above. Additionally, modify the included parts of the definition.
This example works only with the new syntax (see syntactic variants).
Includable files:
name: tabCategories label: Categories fields: - name: categories label: Categories class: info.magnolia.ui.form.field.definition.MultiValueFieldDefinition label: Select category field: name: linkField class: info.magnolia.ui.form.field.definition.LinkFieldDefinition targetWorkspace: category appName: categories identifierToPathConverter: class: info.magnolia.ui.form.field.converter.BaseIdentifierToPathConverter - name: blackOrWhite label: Black or white class: info.magnolia.ui.form.field.definition.SelectFieldDefinition options: - name: black value: black selected: true label: Black - name: white value: white label: White
commit: class: info.magnolia.ui.admincentral.dialog.action.SaveDialogActionDefinition cancel: class: info.magnolia.ui.admincentral.dialog.action.CancelDialogActionDefinition
A dialog file which includes:form:
label: lazy-component
tabs:
# an include within a list, here adding a complete tab
- !include:/module-a/includes/categorization-tab.yaml
label: Yo! 1-tab-only!
fields:
# modify properties of the field blackOrWhite which comes from the include
- name: blackOrWhite
label: Choose color
# an include within a map, here adding the actions for the root (map) item "actions"
actions: !include:/module-a/includes/common-actions.yaml
# add another action to those which already exist from the include
doit:
label: Same as cancel
class: info.magnolia.ui.admincentral.dialog.action.CancelDialogActionDefinition
blackOrWhite
field from the include.
Include a complete file and modify
Create a dialog based on a dialog from the basic
page template of the mtk module. Remove its second tabMeta
tab. This task is similar to the example above in the modify section, but instead of inheriting, you include.
!include:/mtk/dialogs/pages/basic.yaml form: tabs: - name: tabMeta fields: !override
YAML inherit
As the name suggests, with this directive you inherit from an existing registered definition item in order to create a new definition item. Registered items can originate from YAML files, JCR configurations or even from Blossom Java code.
It is not a good idea to inherit from a definition that resides in the same module as the dependent one.
Module files are loaded in order of discovery, which however varies over time. This means that after one reload, a definition might work while the next time you edit the definition or restart your application, it may fail to discover an intra-modular dependency and hence load correctly. Due to this behavior, you should not create such dependencies as they are inherently – no pun intended – unstable.
You can inherit only on the root level - which means you can inherit a complete app but not a subapp. Modify the new item according to your needs.
Registered definition items are known to a registry and can be seen in the Definitions app. Every registered definition item has an "identifier" which is unique among all items of the same type within their registry. Some of the items are defined by name, others by ID. Reference the item to inherit by its identifier.
Inherited items are inherited according to their state known by the registry. (For instance, if an items has been decorated, the registry knows its decorated state. Hence inheriting a decorated item inherits the decorated state of the item.)
Module dependencies due to !inherit
When using !inherit
, you may rely on a definition item which is configured in another module. In this case you must take care of the loading order. If you rely on another module, make sure it is loaded upfront. Use module dependencies to define the loading order of the modules.
module-a
depends on module-b
, module-b
will be loaded before module-a.
The order becomes important, for example, if both module-a
and module-b
decorate the same definition or if module-a
inherits a definition from module-b
.Module dependencies can be defined within a module descriptor.
A generic recipe
- On the first line of your YAML definition, use the
!inherit
directive followed by a colon (:
) and the identifier of the definition you want to inherit from. - Modify the inherited definition.
Examples
Inherit and override a renderer
A new definition: The new renderer named !inherit:freemarker
contentType: application/json
json
inherits everything from the freemarker
renderer but has a different contentType.
Inherit and override a template definition
The original definition you inherit from:
title: a-component renderType: freemarker templateScript: /module-a/templates/components/a-component.ftl dialog: module-a:components/a-component modelClass: info.magnolia.module.jsmodels.rendering.JavascriptRenderingModel parameters: color: blue size: 50
!inherit:module-a:components/a-component title: b-component description: This is a b-bombastic component to test cool YAML features! subtype: dummy-components parameters: !override
- Line 1: Inherit.
- Line 2: Override the
title
property. - Lines 3 and 4: Add more properties.
- Line 5: Suppress the
parameters
property.
The module descriptor of module-b
version: 1.0 dependencies: module-a: version: 1.0/*
module-a
is loaded before module-b
. As a result, the b-component
, which depends on a-component
, can be initialized properly.
Modifying reused configuration
Reused configuration originating from !inherit
or from !include
(when using the new !include
syntax) can be modified. You can:
- Add additional properties and modify properties originating from
!include
or!inherit
. This will merge the included or inherited node with the modifications. - Use
!override
to completely ignore the properties of an inherited or included node. As a consequence, you have to add further properties to the given node.
YAML override
The !override
directive ignores the properties of the node to which the directive has been applied. You have to specify all of the required properties of the overridden definition node.
Example:
A definition to inherit or to include | Inherit | Inherit and override |
---|---|---|
/module-a/templates/pages/l-page.yaml title: L page templateScript: /mtk/templates/pages/basic.ftl renderType: freemarker dialog: module-a:pages/l-page visible: true areas: main: availableComponents: textImage: id: mtk:components/textImage teaser: id: mtk:components/teaser image: id: mtk:components/image link: id: mtk:components/link | /module-a/templates/pages/xxl-page.yaml !inherit:module-a:pages/l-page title: XXL page dialog: module-a:pages/xxl-page areas: main: availableComponents: html: id: mtk:components/html | /module-a/templates/pages/xs-page.yaml !inherit:module-a:pages/l-page title: XS page dialog: module-a:pages/xs-page areas: main: availableComponents: !override link: id: mtk:components/html |
The resulting definition merges the inherited defintion and the modifications area, giving five available components in the main area. | The resulting definition ignores all the properties of availableComponents of the inherited definition, thus allowing only one available component in the main area. |
Overriding list items
Due to the syntax of a YAML list, you cannot apply !override
to a list item. To bypass this constraint, use a YAML map instead of a list to apply override
to an item. Even if the definition class expects a list, the YAML file can define the item with a map.
Example:
A definition to inherit or to include | Inherit |
---|---|
/module-a/dialogs/pages/l-page.yaml form: label: Page properties tabs: - name: tabMain label: L page fields: - name: title class: info.magnolia.ui.form.field.definition.TextFieldDefinition i18n: true label: title - name: navigationTitle class: info.magnolia.ui.form.field.definition.TextFieldDefinition i18n: true label: navigation title - name: windowTitle class: info.magnolia.ui.form.field.definition.TextFieldDefinition i18n: true label: window title - name: tabMeta label: Meta Data fields: - name: keywords class: info.magnolia.ui.form.field.definition.TextFieldDefinition i18n: true label: keywords rows: 3 - name: description class: info.magnolia.ui.form.field.definition.TextFieldDefinition i18n: true label: description rows: 5 actions: commit: class: info.magnolia.ui.admincentral.dialog.action.SaveDialogActionDefinition cancel: class: info.magnolia.ui.admincentral.dialog.action.CancelDialogActionDefinition | /module-a/dialogs/pages/xs-page.yaml !include:/module-a/dialogs/pages/l-page.yaml form: tabs: tabMeta: !override tabMain: fields: title: !override required: true class: info.magnolia.ui.form.field.definition.RichTextFieldDefinition label: Title ... |
Both tabs and fields are defined with a list. To define these properties, it would have been valid to use the map syntax instead. | To apply !override to the tabMeta tab and the title field, we have used the map syntax here. |
Preserving the order of nodes
(Magnolia 5.7.1+) The order of nodes as defined in a decoration via YAML !override
is preserved. This is useful especially if the only change needed to the existing configuration of nodes is their order. Previously, when providing a new config with the !override
flag, the config would be picked up by the system, but any change in the order of the nodes (at the level of the !override
) would not be respected.
For example, the list view in the workbench of the Tours app may be adjusted with the following definition decoration placing the Path column before the Name column:
subApps: browser: workbench: contentViews: list: columns: !override path: name:
Compare with the default view, where the Name column comes before the Path column: