Working with data in Pattern Lab using Handlebars templates

We often use the node version of Pattern Lab over at Wirestream to scaffold out sites before integrating front-end assets into a CMS. It’s a great static site builder that allows our interactive development team to build out separate components, combine them into full templates/pages and work out all the bugs before they get integrated into a CMS.

Working data files into the components allows us to think about how the components will be used and  work out any edge cases. This causes a bit of a learning curve for UI developers that aren’t accustomed to working with JSON data and thinking in customizability for a CMS. So, here are some of the basics of working with JSON data in Pattern Lab, using handlebars templating.

The Set Up

Just a note that the file structure I’ll be referring to isn’t the traditional atoms, molecules, organisms etc. I’ve using a more stripped down elements-components-templates structure. You can restructure your patterns and call them whatever you choose based on your project requirements and pattern lab doesn’t care.

Data Location

Data can be pulled from multiple locations for each component (or element, atom, molecule, whatever your naming convention may be). The data will only show on the level you’ve placed the JSON file. I prefer component or template level data as opposed to one giant global data file. This may require some duplication but feels easier to maintain.

Taking a bootstrap ‘Jumbotron’ component as an example, if the component and data file are placed here:

Folder Screenshot

The data will pull into the jumbotron component only when viewed on the components page in patternlab, here:

Screen Shot 2017-05-29 at 6.03.41 PM

If we create a template and include the jumbotron, it will not contain the data.

Screen Shot 2017-05-29 at 6.07.33 PMScreen Shot 2017-05-29 at 6.10.25 PMThe home template needs it’s own data file (home.json) in the same folder in order to populate the jumbotron data.

Adding the data

So what’s hardcoded and what’s data? Anything customizable in the CMS this markup eventually lands in, should be pulled from a json file.

Taking the jumbotron as an example, let’s say the title, paragraph, and link are all customizable. We’ll replace all those with handlebars expressions. So this:

<div class="jumbotron">
 <h1>Heading</h1>
 <p>Jumbotron Text</p>
 <p><a class="btn btn-primary btn-lg" href="/buy-it" role="button">CTA Button</a></p>
</div>

becomes this:

<div class="jumbotron">
 <h1>{{heading}}</h1>
 <p>{{content}}</p>
 <p><a class="btn btn-primary btn-lg" href="{{href}}" role="button">{{ctaText}}</a></p>
</div>

and the home.json file would look like this:

Screen Shot 2017-05-29 at 6.31.41 PM

{
 "heading": "Jumbotron Heading",
 "content": "This is a Jumbotron!",
 "href": "www.google.com",
 "ctaText": "Click me or else."
}

Screen Shot 2017-05-29 at 6.32.44 PM

Getting Loopy

What if there is a requirement that there can be multiple CTA buttons? In order to mock that up, it’s as easy as using a handlebars {{#each}}{{/each}} expression and an array in the JSON data.

jumbotron.hbs:

<div class="jumbotron">
 <h1>{{heading}}</h1>
 <p>{{content}}</p>
 {{#each ctas}}
 <p><a class="btn btn-primary btn-lg" href="{{href}}" role="button">{{ctaText}}</a></p>
 {{/each}}
</div>

home.json:

{
 "heading": "Jumbotron Heading",
 "content": "This is a Jumbotron!",
 "ctas": [
 {
 "ctaText": "Click me or else.",
 "href": "www.google.com"
 },
 {
 "ctaText": "No, click me!",
 "href": "www.yahoo.com"
 },
 {
 "ctaText": "Don't click me.",
 "href": "www.bing.com"
 }
 ]
}

Screen Shot 2017-05-29 at 6.43.39 PM

I’ve added a “ctas” array to the data, which is an array of objects. Each object includes the ctaText and href.  I then loop over the array in the jumbotron.hbs file with a handlebars each expression.

Conditions – if this show this

What if the content, currently set to “This is a Jumbotron”, is optional? This is where the handlebars {{#if}} {{/if}} expression becomes useful. We don’t want to output the paragraph tag if there’s no content, so we can simply wrap it in an if condition.

jumbotron.hbs:

<div class="jumbotron">
 <h1>{{heading}}</h1>
 {{#if content}}
 <p>{{content}}</p>
 {{/if}}
 {{#each ctas}}
 <p><a class="btn btn-primary btn-lg" href="{{href}}" role="button">{{ctaText}}</a></p>
 {{/each}}
</div>

home.json:

{
 "heading": "Jumbotron Heading",
 "ctas": [
 {
 "ctaText": "Click me or else.",
 "href": "www.google.com"
 },
 {
 "ctaText": "No, click me!",
 "href": "www.google.com"
 },
 {
 "ctaText": "Don't click me.",
 "href": "www.google.com"
 }
 ]
}

Screen Shot 2017-05-29 at 6.56.32 PM

But, what if I don’t want to keep deleting and adding properties to test different variations of one component?

Variations

Pattern Lab includes something called Pseudo-Patterns in order to create variations of patterns.

All we have to do is duplicate the data file, home.json and add the variation name after the template name, separated by a tilde.

Screen Shot 2017-05-29 at 7.02.42 PM

And now Pattern Lab will be updated to include the new variation:

Screen Shot 2017-05-29 at 7.04.21 PM

Conclusion

As you can see, Pattern Lab is very powerful, but also very complex. Using Pattern Lab allows us to work more efficiently and avoid a lot of duplicated markup. It also allows us to quickly update templates or components with data in order to test UI bugs and edge cases, often quicker than working with code already integrated into a CMS.