A User-Friendly Table Field

By Chandra McFarlen

Back to latest posts
table

In general, I shy away from tables on webpages for two primary reasons:

  • People use them for controlling layouts when their are intended only for displaying data.
  • They are not very user-friendly for your average content editor.

And, I'm not the only person with this opinion. Redactor, the crazy-awesome rich text field editor that Craft CMS uses, recently stopped including the table button in its essential editing tools. While there are ways to add this button back, I believed that there had to be an easier way.

The Objective

We have a customer that needed the ability to add tables on their website for what they were genuinely intended for: displaying data. Here were the requirements:

  • Adding, and editing tables needed to be so user-friendly that no training would be required.
  • Our client needed to be able to set the number of columns and rows when adding and editing the table
  • The table needed to match the style of the site's custom design without any extra effort by the client.

The Solution

Enter the Matrix field by Craft CMS! I was already using a Matrix field for what I called my Complex Content field to handle different kinds of content (i.e. images, paragraphs, headlines, quotes, etc) in what is called longform or modular content editing. See this video for a quick preview of what I'm talking about.

So, the logical next step was to create a Table block inside my Matrix field.


Craft CMS comes with a Table field type, but I was surprised that you have to set the column headers when you create the table field itself. This would not meet my second requirement as we wouldn't know exactly what the table was being used for until it was being created by the content editor. I conquered that dilemma by giving the columns ambiguous headings in the field setup:


For the field's instructions, I noted that the first row would be what is actually used for the column headers when the table is seen on the site.

So here it is in action in when you are editing an entry:


And here is my template code:

...

{% elseif block.type == "table" %}
  <div class="tablesaw-bar mode-stack"></div>
  <table class="tablesaw tablesaw-stack" data-tablesaw-mode="stack">
    {% for row in block.tableColumn|slice(0, 1) %}
      <thead>
        <tr>
          {% if row.column1|length %}<th>{{ row.column1 }}</th>{% endif %}
          {% if row.column2|length %}<th>{{ row.column2 }}</th>{% endif %}
          {% if row.column3|length %}<th>{{ row.column3 }}</th>{% endif %}
          {% if row.column4|length %}<th>{{ row.column4 }}</th>{% endif %}
          {% if row.column5|length %}<th>{{ row.column5 }}</th>{% endif %}
          {% if row.column6|length %}<th>{{ row.column6 }}</th>{% endif %}
        </tr>
      </thead>
    {% endfor %}
    {% for row in block.tableColumn|slice(1, length) %}
      <tr>
        {% if row.column1|length %}<td>{{ row.column1 }}</td>{% endif %}
        {% if row.column2|length %}<td>{{ row.column2 }}</td>{% endif %}
        {% if row.column3|length %}<td>{{ row.column3 }}</td>{% endif %}
        {% if row.column4|length %}<td>{{ row.column4 }}</td>{% endif %}
        {% if row.column5|length %}<td>{{ row.column5 }}</td>{% endif %}
        {% if row.column6|length %}<td>{{ row.column6 }}</td>{% endif %}
      </tr>
    {% endfor %}
  </table>
 <hr>
{% endif %}

...

Twig's slice filter allows me to only show the first row as table headers and the rest as normal table content. If our client only wants a three column table instead, all they have to do is leave the last three columns blank. The table is still output correctly since we are checking the length of a cell's content before hand.

And here is the final product with our own personal styling touches:


This setup gives the client a lot of freedom all while keeping the table easy to use and true to the site's design! No more looking at code or even short code. No more having to know what class to apply to the table. No more frustrated clients!

I would love to hear your thoughts on this approach! I think my next step will be to optimize the code a little by using the Craft cache tag.

blog comments powered by Disqus