Published: Fri 19 Oct 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:

  1. {% for list_item in list_items %}
  2. {{ list_item }}
  3. {% endfor %}

Then list.yml has something like this:

  1. list_items:
  2.   - join():
  3.   - include():
  4.   pattern: content-teaser
  5.   - join():
  6.   - include():
  7.   pattern: content-teaser
  8.   - join():
  9.   - include():
  10.   pattern: content-teaser
  11.   - join():
  12.   - include():
  13.   pattern: content-teaser
  14.   - join():
  15.   - include():
  16.   pattern: content-teaser
  17.   - join():
  18. -- 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

  1. list_items:
  2.   - join():
  3.   - include():
  4.   pattern: content-teaser
  5.   - join():
  6.   - include():
  7.   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:

  1. list_items:
  2.   - join():
  3.   - include():
  4.   pattern: content-teaser
  5.   - join():
  6.   - include():
  7.   pattern: content-teaser
  8. -
  9. -
  10. - 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:

  1. card_title: 'My Card Title'
  2. card_image: '<img src="/path/to/image.jpg">'
  3. 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:

  1. card_title: 'My Card Title'
  2. card_image: false
  3. card_text: false

Now my variants can look as simple as:

  1. card~with-image.yml
  2. card_image: '<img src="/path/to/image.jpg">'

And card~long-title will be just one line:

  1. 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.

If you like what I write, you might like to follow me on Twitter @markconroy

Add new comment

Restricted HTML

  • Allowed HTML tags: <a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.