Building Vue Components so Back-End Developers Won’t Hate You

Because at the end of the day, it’s all just HTML, CSS, and Javascript anyway

By Ian Johnson, a Sr. Front End Engineer at Skilljar

Me, reenacting a backend developer’s probable sadness when they have to work with Javascript. 📷 by Huy Ngo.

Just kidding, they don’t hate me, they hate the Javascript — but who wouldn’t when we keep rebuilding our tooling every few years 🙄

Back in my day…

On the grand scale, reactive frameworks (and by that I mean declarative, rather than imperative, ala Vue, React, Angular, etc) are young — with jQuery around since 2006 and the first of the reactive frameworks taking off in 2012.

We’ve only had a bit more time with these new frameworks than we’ve had without them (yes I’m aware the internet existed before jQuery, but it was a dark time; you should see my first Geocities website).

https://insights.stackoverflow.com/trends?tags=angular%2Cangularjs%2Creactjs%2Cjquery%2Cvue.js

Then, on the scale of reactive frameworks themselves, Vue is young — with AngularJS taking off in 2012, React in 2014, (Angular again in 2015, this time without the “JS” in its name 👍), and Vue in 2015.

Six years and four frameworks? It’s understandable that not every developer wants (or has the time) to jump on every new Javascript framework that takes the world by storm. Anything we as front-end devs can do to wrap up some of that magic can make the lives of our back-end, QA, support engineers, etc. a little easier.

What’s this history lesson for?

So we as front-end developers might understand the problem I’m tackling in this article — how to build front-end components for others in our organization. We all know how, what, and why we built our own components, modules, classes, etc — but us knowing why we did things doesn’t scale very well beyond, well… an organization of us.

Awkward sentence right? Lots of references to oneself in there — and Skilljar sure isn’t an entire team of front-end developers either. I’m one of two front-end developers working alongside an entire team of back-end devs that may one day have to look at — or worse — implement front end code 😉

So “my” code? That’s also their code.

Just as major languages (Node with NPM, Ruby with Gems, PHP with Composer, Python with PIP, etc) all have packages — reactive frameworks allow us to wrap up complex HTML, CSS, and Javascript into “components” that all developers (back-end, other front-end, junior) can implement without needing to understand the internals.

So how do I make the world a better place then?

At the end of the day the server is spitting out HTML, CSS, and Javascript anyway, so let’s not over complicate this component architecture by reinventing the wheel.

Aka not this — let’s call it the <search-form> example

There’s no way <search-button-icon> rolls up enough functionality to warrant being it’s own component.

There’s no reason to re-invent an entirely new, custom HTML spec for your site; it only makes it impossible for others to reason through all your front-end code — and remember, it’s still all output as HTML, CSS, and Javascript.

Ok… then what SHOULD I do?

What if I told you that your components don’t need to be overly complicated — that you can write impressive, modern components, that can still be easily understood by all?

At Skilljar, for example, we recently launched a new Vue Datatable component that looks a little something like this —

One of our many new Vue datatables we’re rolling out on the Skilljar customer dashboard

Implemented with this —

We wrapped up an entire datatable’s worth of complex functionality into what is no more than a regular HTML element with two little filter-children 🤯 (that’s a head explosion emoji if you can’t see it).

And still using only three single file Vue components

  1. Datatable.vue
  2. DatatableDateRangeFilter.vue
  3. DatatableCheckboxFilter.vue

The two filter components, DatatableDateRangeFilter.vue and DatatableCheckboxFilter.vue, are children components designed to be nested within the main Datatable.vue element via its <slot></slot> element¹.

How’s this any different than that <search-form> example?

Architectural decisions are always a challenge. You could look at that datatable screenshot and wonder why the search box isn’t its own Vue component, or why the pagination isn’t, or the per-page dropdown, etc— but there’s just not generally a black and white answer. It usually boils down to understanding who’s going to be using your component as well as how it’s going to be used both now and in the future.

I chose not to architect those as separate components because, in my interpretation, they’re really only features that are either on, or off —and so were built to be toggled with an attribute on the <sj-datatable> element, i.e. <sj-datatable :hide-features="['search', 'pagination', 'per-page', /* etc */]">).

The filters, however, were going to be dynamic in both number and types — which meant we needed to either pipe some complex object into the component property (rather than an on/off toggle like above), or it was time split filters out into their own components.

Note: If there was only ever going to be one date filter, or one checkbox filter — maybe with some parameters — those probably also could’ve been “features”, but we were going to need anywhere from zero to multiple filters, all with different parameters, depending on the type of data we were loading into each datatable.

Probably not my actual desk, but that is my actual code

I still have no idea what you’re talking about

Our goal here is to —

  1. Help someone who’s not as familiar with Javascript to still be able to roll out our complex components without our help (empower our coworkers!).
  2. Build self-contained blocks of HTML, CSS, and Javascript that can be copy/pasted with obvious and self-explanatory properties.

We want the addition of a new datatable to be as easy as a backend dev building out their own API endpoint and copy/pasting some previous <sj-datatable> implementation and thinking —

“Oh hey, if I just update the api-endpoint and csv-endpoint properties and… we don’t need filters right now so I’ll delete those — and… I’m done? Heck yeah.”

Because in the world of front-end development, the closer you can make your fancy reactive components look and feel like something commonly understood and framework agnostic — like HTML — the easier you can make everybody’s lives.

Alright, so give me some guidelines or I’m just going to steal your datatable…

No! I believe in you!

First, wrap up enough complex, reusable functionality that you’re actually saving both time and sanity, i.e. don’t rewrite the HTML spec with your own <customButton> and <customInput> components.

Instead of this, which (is probably) overly-abstracted and (again, probably) exposes internals not actually meant to be accessible to other devs—

Unless each of these components actually wrap up enough complexity to warrant their own component, this is a lot of abstraction and boilerplate for just some HTML.

Try rolling everything up into the one component you want to be reused, perhaps with toggles for simple on/off features like the search button. And don’t just nest all those previous custom components inside this component, inside this should probably be regular old HTML.

One reusable component with a single property and a feature toggle is significantly easier to understand.

Second, keep your component’s styles scoped to itself, in a single file Vue component this looks like —

And finally — document, document, document.

The bane of all our collective existences is bad documentation, so if you’re going to go to all the trouble of creating these beautifully reusable custom components for your organization — document them!

Even if the entirety of your documentation is just an example of the component with all the available properties, it’s better than a documentation black hole.

This is what the (minimal) spec for our Vue Datatable looks like —

Not the most verbose, but if they understand HTML and Javascript they should be able to parse through this.

So there.

I mean, uhh… so there you have it!

If you’re another front-end developer working in a primarily back-end dev organization, I’d love to hear how you tackle building components for an audience not necessarily fluent in your framework ✋


¹ Lame footnote

Unfortunately components can’t listen for events emitted by anything in their <slot> tags, so inside these <sj-datepicker>'s we can’t emit an on-date-selected event and listen for it on the <sj-datatable> component to dynamically update our data.

I‘ve tried getting clarification, but haven’t had much success— https://github.com/vuejs/vue/issues/8656, so we’ll see where it goes as two previously have already been closed without much more.

Interested in learning more about Skilljar? Check us out at https://www.skilljar.com/. We’d love to chat with you if you’re interested in joining the team. You can learn more about open positions at https://www.skilljar.com/about/careers/

Shout out to my coworker Huy Ngo for both being my photographer and proof-reader on this article 👊