I recently attended the ARTIFACT conference in Austin, TX, and was inspired by a few talks about accessibility through the lens of site performance. It became clear to me that there is this tendency to rely on big JavaScript frameworks to handle the work — like React, Vue, and Angular — but that can be overkill in some cases. That is, negatively affecting site performance, and thus accessibility. At the same time, these frameworks can make development easier and more efficient for developers. My big takeaway from the conference was to see how a fast, performant experience can be balanced with my own development process.

This was on my mind as I was building a list-filtering feature on a project a few days after the conference. Pretty standard stuff: I needed a list of posts and some category filtering. I was using CraftCMS for front-end routes and templating as well as some Vue components here and there for some added JavaScript juiciness. Not a full-on “single page app” but more like a sprinkle of Vue.

The typical way one might approach this is to:

  1. render the page with an empty div using Craft/Twig
  2. mount a Vue component to that div
  3. make an Ajax call from the Vue component to an API to gather the posts as JSON
  4. render the posts and tie in the filtering.

Since the posts are held as an array within Vue, dynamic list rendering is a pretty cut and dry task.

Simple. Done, right? Well… that extra Ajax request means the user is presented with no content on the initial load depending on the user’s network, which might take some time. We could add a loading indicator, but maybe we can do better?

Preferably, the posts are rendered on the initial page request from the CMS.

But how do we get the static HTML “hooked up” with Vue for the filtering?

After taking a step back to rethink the problem, I realized I could use v-if directives to achieve the same thing with some inline JavaScript from Twig (“in the loop”). Below, I’ll show how I went about it.

My original project used CraftCMS, but I’m going to do the demos below in WordPress. This is just a concept. It can be applied to CraftCMS/Twig or any other CMS/templating engine combo.

First we need a filtering UI. This will likely go above the start of the loop in an archive template.

 'post_tag', // I used tags in this example, but any taxonomy would do
  'hide_empty' => true,
  'fields' => 'names'
] );

if(!empty($terms)): ?>
  
Filter:

Showing posts tagged {{ tag ? tag : 'all' }}.

Following along with the code, we get some tags from WordPress with get_terms() and output them in a foreach loop. You’ll notice the button for each tag has some Vue directives we’ll use later.

We have our loop!

    
" v-if=' 'names'])); ?>.includes(tag) || tag === ""' >