Published: October 19, 2018
Can I Stop PatternLab Variants from Inheriting Data from their Parent Component
I have a card component with a title, image, text, and link. How come all my card variants are inheriting all the values from the default one? Short answer, you don't. It's a feature, not a bug.
Where this really becomes frustrating is when you have a pattern that lists a number of items in an array. In that case, all variants will have (at least) that many items, even though you may want fewer.
For illustration:
list.twig has something like this:
{% for list_item in list_items %}
{{ list_item }}
{% endfor %}
Then list.yml has something like this:
list_items:
- join():
- include(): pattern: content-teaser
- join():
- include(): pattern: content-teaser
- join():
- include(): pattern: content-teaser
- join():
- include(): pattern: content-teaser
- join():
- include(): pattern: content-teaser
- join():
-- loads of more teasers for the main listing page
Now you want to create a variant of list such as list~related-articles, but with only 2 items. You'd expect this would work
list_items:
- join():
- include(): pattern: content-teaser
- join():
- include(): pattern: content-teaser
But, no. This will still render as many items as were in the parent component. That's the beauty (a feature, not a bug) of PatternLab's inheritance system. To stop it you need to do something like this:
list_items:
- join():
- include(): pattern: content-teaser
- join():
- include(): pattern: content-teaser
- - - and so on, so each extra one is basically set to 'false'
When we do this with a component such as a card, we might also want to have variants such as card~no-image, card~no-text, etc. In this case, we'd have a card.yml like so:
card_title: 'My Card Title'
card_image: ''
card_text: 'The text of the card will go here'
However, if we create variants, each of the items in card will be inherited to the variant. You'll notice this if you try to create one super mega component for all variants of a hero component for example (hero title, pre-title, sub-title, image, alignment, cta buttons, etc).
In this case, what I do is create a default component card.yml or hero.yml and give it only values for items that will more than likely be in all variants (basically whatever you are going to mark as a required field in Drupal (or whatever CMS you are using)), then set all others to 'false' in the component. Now when I create variants I only need to override the specifics for that variant, since everything else that is being inherited is already set to false. I also create a 'Kitchen Sink' version of the component which shows every item in action but DO NOT create this as the default/reference component.
My default card.yml might look like this:
card_title: 'My Card Title'
card_image: false
card_text: false
Now my variants can look as simple as:
card~with-image.yml
card_image: ''
And card~long-title will be just one line:
card_title: 'This is a long title on a card just to illustrate what happens when it wraps to more than one line'
And that is why this is a feature, not a bug - it allows us to write variants very simply and quickly. Is there a better way of doing this? I'm not aware of one. If you are, drop it in the comments. Thanks.