Component-Based Frontend in Drupal
Tags: drupal, components, twig, webdev
Published: 2021-09-27 04:49:56

## What is Component-Base Frontend Development
First of all, **Component-Based is an approach to UI Design and Development**.

Shortly, your website is no more designed as a set of pages, but as a list of small and reusable blocks (components).
In other words, your pages become "simply" compositions of these blocks, sorting them in different order.

Components are not tied to specific page or sub-page but should be reused throughout the whole website.

If you're implementing a theme for a CMS, it's up to you to decide to use components to just build a "fixed" set of templates or use them to let the client build pages in a flexible sort-of-composer way:
you can use Paragraphs in Drupal, Matrix field in Craft CMS or Flexible Content field type of WordPress ACF Pro plugin just to cite a few.

This is an example list of UI components:
- hero
- gallery
- card
- cards
- cards-carousel

The actual names of your components is up to you, designers and developers. They should be as more abstract as possible, but I suggest you to find a good compromise avoiding overthinking.

As I said before, Component-Based approach is not only a dev-tech-code thing, but it first involves designers.
From the design point of view, **the best is to have a complete and clear collection of all components involved in the project, and then the actual design of pages**.

As a developer you start coding first by building the collection of all components and then you can go on building pages.

In my humble opinion this paradigm is amazing when working with a CMS since **it lets you write the frontend code you want detached from the underlying CMS, in a sort of decoupled way**: this way CMS becomes more your source of data rather then a magic box where your markup comes from.

Yes, if you're used to just style the HTML coming from the default templates of your CMS, this approach is going ask you to write more html, in some cases lots of templates (Drupal), but you'll have full control over it and it'll be easier to integrate 3rd party frontend libraries/components.

Actual implementation details depend on the CMS you're building the frontend for, but more or less this is path for the win: **you first code the abstract components, then you connect dynamic data coming from the CMS to the components params/props, and then you build the page**.

## Why you should start using it
Switching to a Component-Based Design and Development paradigm means:
1. more collaboration between designers and developers at the early stages of the project;
2. developers can concentrate on implementing pieces of UI unchained from the underlying CMS used: your frontend code is less dependant by the CMS, so you're free to use whatever markup/classes/architecture you want;
4. you can implement a style guide shared between the team that can help a lot in terms of keeping consistency during the project
5. your client or content editor people will easily get one "flexible" page template rather than a set of prefixed page templates. I guess it's a great value added to the project in the sense that your clients will be able to build whatever kind of page they'd like in the future just using and rearranging the building blocks.


## How to implement Component-Based Frontend Development in Drupal
This is my way of implementing Component-Based Frontend Dev in Drupal.

1. **Markup (HTML)**: components are implemented as Twig files, and live in '/templates/components' folder inside your theme folder.
2. **CSS**: a separate scss file for each component (I love ITCSS architecture and I use gulp and sass to build the final compressed css file). BEM methodology drives me for classes names.
3. **JavaScript**: when required, JavaScript is implemented as ES6 module and bundled with other modules (using gulp, babel and rollup for the build). Using CSS classes with "js-" namespace is a great way to target blocks from JavaScript (eg. js-carousel)

This is an example of the markup of the hero component:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o5c122g5dnaleznlosdj.png)

As you can see this component is expecting to receive just 3 parameters/data/props: **image, title and text**.
I'm able to use the markup I want with all the classes and methodologies / architectures I want: I'm using BEM, with namespaces and in particular in this case I'm using the 'js-hero' class to target this block from JavaScript.

This is an excerpt of the related Scss file:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3ha3uyy1yyo6yplndora.png)

## Connecting Components to Drupal
And now the most complicated part: passing data coming from Drupal to components as parameters/data/props.

Inside each specific Drupal Twig file I simply go with a Twig include statement passing an object containing relevant data coming from fields:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ohjr37ox2qigphhkm02q.png)


The "specific Drupal Twig file" depends on how you structured the content, but this can be easily done for:
- nodes templates (eg. node--page.html.twig)
- views templates (eg. views-view-fields--hero.html.twig)
- paragraphs templates (eg. paragraph--card.html.twig)

Often the tricky and time wasting part is to access field plain value.

If you've ever worked with Craft CMS you know that accessing field values with this CMS is straightforward thanks to their amazing Twig API, but in Drupal it's not so easy.

**Drupal makes the assumption you usually don't want plain value from a field to be used directly in Twig templates, but you usually want a formatted value or worse a prebuit markup depending on the field formatter and the templates coming from modules and base theme you're using**.

So, this is my short list of code snippets to access various fields type data:

### simple text field (plain or long/html)
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w2a8rwek06l7logbwtyh.png)

### single image field
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/g1dc4vndpmolnc7a6ei7.png)

### building a custom markup for a multi image field (pay attention: you have to use node.field_gallery and not content.field_gallery)
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/smeaz2yhp9m5j5exx4bz.png)
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mtc3qg1vn02fbrn4fs1f.png)

### url and text from link field type
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i5u6nicwz57v7vwbcicn.png)

### File field with description
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8lipeugc3r5iq5ov07to.png)

## Interesting links about component-based development
- https://www.droptica.com/blog/component-based-design/
- https://www.cmsdrupal.com/blog/how-component-based-approach-speeds-your-ui-design-process