Data inheritance in Pattern Lab

When Pattern Lab renders a pattern, it does not by default include the data for any included patterns. There are plugins that can be used to include this data, but the many different ways to include patterns within another and to implement data inheritance can cause confusion.

The many faces of Pattern Lab

Before getting to the main topic, it should be noted that there are two versions of Pattern Lab (PHP and Node) and several editions of both versions. While trying to keep generic where possible, this article is mainly focused on the PHP version and Twig PatternEngine, which are bundled together in the Twig Edition of Pattern Lab PHP.

Including patterns in one another

In Pattern Lab a pattern can be included within another by using Pattern Lab’s shorthand include syntax or the templating language’s own include syntax. The shorthand include syntax is nice, but will not work outside Pattern Lab. This is why it is best to use the templating language’s own syntax if you want to keep Pattern Lab in sync with a production environment.

Twig’s include syntax supports namespaced paths. Namespaces are a great way to avoid both absolute and relative file system paths in native Twig includes. Pattern Lab automatically registers Twig namespaces for the top-level pattern folders, and the Twig Namespaces Plugin can be used to add more. The Component Libraries module can be used to add Twig namespace support and use the same namespaces in Drupal 8 themes.

Twig namespace support was added to Twig PatternEngine in May 2016. However, proper lineage support for namespaced includes was only added to the official versions of Pattern Lab PHP Core and Twig PatternEngine in October 2017. This made Data Inheritance Plugin work with Twig namespaces as well. Data Transform Plugin currently has support for namespaced includes in its development branch.

Types of data and default data inheritance

Pattern Lab supports global data files and pattern specific data files. Pseudo-pattern data files are a third type of data file, but in most situations they can be considered to be pattern specific data.

By default Pattern Lab merges pattern specific data with global data, with pattern specific data taking precedence.

How plugins currently implement additional data inheritance

Data Inheritance Plugin merges pattern specific data from included patterns (lineage data) with the current pattern’s pattern specific data. The current pattern's data takes precedence. This happens before the default merge with global data. The merged data is passed to the template engine when the current pattern is rendered.

Data Transform Plugin hooks into the Twig template engine. When the template engine performs an include operation, Data Transform Plugin fetches data for the included pattern from Pattern Lab’s data store. It merges pattern specific data with global data, with pattern specific data taking precedence.

In other words:

Data Inheritance Plugin

  • merges pattern specific data of all included patterns with the pattern specific data of the parent pattern
  • merges global data only once, with the previously merged pattern specific data
  • passes data to the parent pattern only

Data Transform Plugin

  • merges global data with pattern specific data individually for every pattern
  • passes data individually for every pattern

Practical implications of the different approaches

In many cases there might be no differences in the results, especially if the parent pattern’s data also contains data for all the included patterns or if the variable names used in the patterns are all different.

But there are some cases where the end results will differ depending on which plugin is used. These cases often involve missing pattern specific data for variable names used in more than one pattern.

Examples

I will use the following data files to demonstrate these differences:

Global data file (data.json):

{
"title": "Global title",
"content": "Global content"
}

parent pattern data file (parent.json):

{
"content": "Parent content"
}

child pattern data file (child.json):

{
"title": "Child title"
}

The parent and child patterns both have variables called title and content. The parent pattern includes the child pattern.

Merged data can flow up from included patterns

Using Data Inheritance Plugin, the title for the parent pattern will be ‘Child title’ and using Data Transform Plugin it will be ‘Global title’.

Global data merged with pattern specific data of included pattern takes precedence over parent pattern’s data

Using Data Inheritance Plugin the content for the child pattern will be ‘Parent content’. Using Data Transform Plugin it will be ‘Global content’

Is one approach better than the other?

The different approaches can be used to fulfil different kinds of requirements, and the choice might depend on how the patterns have been implemented.

Data Transform Plugin, including its data inheritance functionality, was written specifically with Drupal theme development in mind, and is compatible with the default Drupal template rendering style of not actually using Twig includes.

I would be very interested in learning about cases where one approach is definitely better than the other.

When Pattern Lab renders a pattern, it does not by default include the data for any included patterns. There are plugins that can be used to include this data, but the many different ways to include patterns within another and to implement data inheritance can cause confusion.