Data Driven Design icon

Nested Matrices in Craft CMS 3 Using Super Table Plugin

Craft CMS is an incredible tool that helps developers and users get the best of two worlds. For people on the technical side, it delivers ease of development and easy customization. And for users, content management is intuitive and simple. We're a big fan here at Data Driven Design, and as we've come across increasingly complex demands we've discovered the many ways Craft can be configued for use as well as the many plugins that can help take a website to the next level.

The Problem

In doing work for SEO on our own site recently, we knew we needed to develop a system of pages that had particular URL structures. Since we wanted these to have a nested structure where the child pages can rely on the URL of a parent page, it seemed like using Craft's Structure section type was the right fit. It helps that the pages we were developing were a listing of the services that we offer as a company. Craft's documentation gives us a big thumbs up for our plan, specifically mentioning it's a good fit for services pages in their documentation.

Craft CMS Structure documentation

The problem we faced was that the design that was created for the set of pages differed dramatically based on whether it was a high-level page for listing all of our service offerings, or a service detail page that could be used to explain an individual service or group of related services. What this meant is that we had two separate sets of components for the pages, but both needed to be available on the Services pages for us to use in the correct places. We also wanted to make the content entry as intuitive as possible.

The two basic options we had were:

  1. To make all of the content areas individually available in a matrix and then simply select the ones we needed depending on the type of page. This is fairly straight forward and while there's no problem with ease of content entry, it is not very intuitive and can be prone to user error.
  2. Use nested matrices, where the top level matrix would be a selection between the two types of pages. You could then choose which type of page and all of the appropriate blocks would be inside that selection, making content entry more intuitive. The trade off here, is that the backend set-up woud be a bit more complicated and we would need a way to make matrices inside of matrices.

After doing a bit of research we discovered that a plugin exists to make nested matrices and decided to take our development down the 2nd route. The goal was to figure out whether this was a good option to use on future projects and what challenges and drawbacks were attached to this choice.

Our Solution

Here are the steps we took to try out this new approach with matrices inside of matrices.

1. Go to the Plugin store in Craft's CMS backend and install the Super Table Plugin.
Super Table Plugin
2. Set up content entry with the top level choices between "Services page" and "Service Page" under Settings > Fields as usual.

After fiddling with the different types of layouts allowed in the Super Table, I prefer the Matrix Layout.

Services Blocks Top Level Matrix using Super Table
3. Inside of each of these "pages", create a matrix with the fields that are relevant to the page.

For the "Services" we had fewer blocks:

Services Blocks Nested Matrix for Services using Super Table

But for the individual "Service" page we had many more options we wanted to include:

Services Blocks Nested Matrix for Service using Super Table
4. Add the the field set to the page itself and go forward with content entry.
Craft CMS services section content setup
5. Hook the content up using Twig.

This step was a bit more complicated than we expected because the Plugin itself thinks of the nested matrices as tables. It takes a bit to suss out this fundamental part of Verbb's thinking, but having access to their documentation helps immensely. To make the layout compartmentalized, we used partials to insert the appropriate content blocks in the right spots. In our _entry.html file we extended the base layout of the site and retrieved all of the servicePageBlocks.

{% for row in entry.servicePageBlocks.all() %}
{% endfor %}

Inside of this loop, after retrieving them, we needed to make sure that we got all of the fields to loop through like so:

{% for field in row.getFieldLayout().getFields() %}
{% endfor %}

We used a switch on the field's handle and, inside of each, made sure to check that the row had content. Without this check, we found that it will try to insert content, but finding none, may have a container, spacing/styles visible.

{% switch field.handle %}
    {% case "servicesPage" %}
        {% if row.servicesPage | length %}
            {% include 'service-landing-page/_services.html' with {'matrix': row.servicesPage.all(), 'entry': entry } %}
        {% endif %}
    {% case "servicePage" %}
        {% if row.servicePage | length %}
            {% include 'service-landing-page/_service.html' with {'matrix': row.servicePage.all() } %}
        {% endif %}
{% endswitch %}

For reference, here's the complete solution for the super table logic on the page:

Data Driven Design services blocks super table code

As youcan see from the above code, once I've done this logic, I am passing the content into another partial (_services.html or _service.html depending on which case is relevant), and then doing a more typical set of logic that should be familiar to those who have used Craft's matrix type before.

Here's what it looks like on the services page:

Data Driven Design services block super table code

And here's what it looks like on an individual service page:

Data Driven Design services page super table code


Our usage of the Super Table Plugin was a bit more complicated than we originally envisioned and it did take some time to review Verbb's documentation and work out how to use the plugin in our unique scenario. While the content set-up in the backend of craft was somewhat more complex than the alternative solution, it is much easier for a user who wants to get in the CMS just to enter content. Depending on the site's size, page complexity and other factors, it might be right fit for some clients.

While we're obviously a development company ourselves and didn't necessarily need content entry to be as organized as this solution allows, it was important to work through the process to see how long the implementation would take, where the complexities lie, and work through some of the content scenarios where we would recommend and implement content set up like this.

Your implementation of the Super Table plugin will likely be unique. But, hopefully, this example will help you see how to break this powerful plugin down into components that can work for your site.

Need a website solution?