How to extend an existing content feature
There will often be use cases where a developer wants to extend an existing content type by adding additional fields without requiring that those fields be added to every site. For example, the Drutopia Event module provides an event content type. Say we want to provide an optional location field for every event. How to do this?
Drutopia features have been intentionally created in a modular way trying to limit the number of dependencies between features. This means that when we want to add fields that would otherwise create dependencies, we do so in what might be called a “bridging” module—a module that bridges by adding a new field to an existing content type provided by another Drutopia module. We do this using the Config Actions module.
The Drutopia Storyline feature provides a working example that can be used as a model to follow when using this pattern. You will be creating two new modules. They can, however, be bundled into one project.
Here’s an outline of the steps to follow:
Start by creating and configuring the field as well as its form and view displays. In the example, our new field is
field_storyline
and is added to thepage
content type.Create a new base feature (in our example
drutopia_storyline
).This will provide the field storage for the new field.
Add a dependency on config_actions manually by editing the feature’s
.info.yml
file .Edit the exported
.yml
file for the field storage, settingpersist_with_no_fields
totrue
.
Create the bridging module (in our example
drutopia_page_storyline
). You can add it directly to the directory of the base feature, so that they are both in the same project.The field will be placed in the
config/install
folder.Edit the
.info.yml
file of the exported feature to add dependencies on both the base feature (in our case,drutopia_storyline
as well as the module that provides the content type you’re adding the field to (in our case,drutopia_page
).Manually write config actions files to add your new field to relevant configuration. Save these files to an
actions
folder inside theconfig
folder. The actions will include the changes impacted by adding the new field such as the form mode and any display mode used.To determine what code needs to go into the new config actions files, use Drupal core’s built-in functionality to export a single configuration item. For example, in our case, assume one of the configuration changes was to add
field_storyline
to thefull
view mode thepage
content type.Navigate to Configuration > Development > Synchronize Configuration > Export > Single. For “Configuration type” select “Entity view display” and for “Configuration name” select “node.page.full”.
In the YAML markup that’s displayed, look for occurrences of the name of the field you added. In our case, this is
field_storyline
and they occur in two places: underdependencies.config
and undercontent
. Both of these changes need to be registered in a config actions file.Create a new file, naming it for the config item you’re altering. The file name is given on the export form, below the YAML text area. In our case, the file will be named
core.entity_view_display.node.page.full.yml
. Rather than working up a new file from scratch, look for one you can model yours on. See the examples in Drutopia Page Storyline. From the exported YAML code, you can copy and paste in the entire section giving the configuration for your field. See the below example fordrutopia_page_storyline
, which includes comments.
plugin: 'add'
actions:
# Add config dependency.
config_dependencies:
path: ["dependencies", "config"]
# Edit the next line to use the name of your field.
value: "field.field.node.page.field_storyline"
# Add the entity form display settings.
content:
path: ["content"]
value:
# This is the portion to replace with what you copy from exported YAML.
field_storyline:
type: entity_reference_paragraphs
weight: 3
settings:
title: Paragraph
title_plural: Paragraphs
edit_mode: open
add_mode: button
form_display_mode: default
default_paragraph_type: storyline_header
third_party_settings: { }
region: content