Data Driven Vue.js

One of my favorite development paradigms with popular javascript frameworks (Angular, React, Vue etc.) today has been the concept of “data-driven” UI development. You define data on a component and it drives the view. I’ve been using Vue.js in production at Educents for the past few months and the creators of Vue have done a good job documenting best practices. I will discuss how to create data-driven components in Vue.js, but the concepts can be extended to other popular frameworks. Our goal is to create components which are clean, extendable, testable and most importantly fun to modify later!

Creating an HTML Table from a Backend REST API

For this example, I’ll be displaying data in an HTML table. If we want to display data in a <table> , it might be tempting to start out creating many different html blocks for each data table, based on it’s number of columns, rows, css classes, actions for editing, etc. Resist the urge and think about how we can make it data-driven! It is important to separate the data layer from our view layer so that we can have components that aren’t fragile. Adding a column? No sweat. Disparate datasets all with different functionality? Brilliant!

Simple data table built with Vue.js

I’m using axios to send an HTTP request to jsonplaceholder.typicode.com which is a great tool for prototyping actual HTTP calls. We’ll get a list of users and display it on the page.

[
{
"id": 1,
"name": "Darren Jennings",
"username": "dardrone",
"email": "darren@educents.com",
...
"company": {
"name": "Educents",
...
}
},
...
]

Hello.vue component, uses a custom<data-table> component with properties. Properties define the customization of the component. For instance, every time we want to display some data in a table in our app, we don’t expect to construct the entire DOM structure, nor the CSS classes, or even basic functionality that all data tables should have (sorting? CRUD?). But we expect that if we need to display data in another part of our app, that we can reuse the work we’ve done before.

Make the ‘V’ in MVC Great Again

The class Api has one static method to fetch our users. The Hello.vue component gets the users when the component is created in the Vue.js lifecycle and then passes the data property to our DataTable.vue. Our Hello component shouldn’t have to worry about dataTable stuff, but rather it interfaces with its properties to configure how it will render.

So Hello.vue will handle what happens when you click a row in the table. In this example, it’s trivial (console.log), but it demonstrates the ability of Vue.js components to pass parent methods as properties as well as Objects, Strings, etc. As the Vue.js documentation states:

A common pattern for parent-child communication in Vue is passing down a parent method as a callback to the child using props. This allows the communication to be defined inside the template (where composition happens) while keeping the JavaScript implementation details decoupled.

DataTable.vue

The best thing about our DataTable.vue component is that from the moment you look at it, you know all of the data properties it needs, which are revealed to us in the properties and data options. From the Vue.js documentation:

It’s helpful to think of the data option as the schema for your component state. Explicitly listing possibly-present properties in the component definition makes it easy to understand what a component may contain when you look at it later.

It might seem redundant to pass “columns” to the data table, as it should have the capability to simply read the properties of the Users array returned from the API and just display them, BUT it allows us to pick and choose which columns we want to display. On the DataTable.vue I’ve created a method that filters the data array by the columns passed in. I’ve also stubbed out a method called sort which is triggered when you click a column name. The actual sorting of the data is best left for you to implement. 🤗

Simplified HTML Template

Inside of DataTable.vue we don’t see a large object specific HTML template, but rather a generic template for any dataset. With v-for you can not only iterate over arrays, but objects as well, which gives us the ability to go through both the users array, as well as through the properties in the user object.

<tr v-for=”obj in filterdData” @click=”clickRow” :id=”obj.id”>
<td class=”label-cell” v-for=”property in obj”>{{property}}</td> </tr>

If our user API added a column that we wanted to show, we would simply add it to our columns array in Hello.vue.

Conclusion

To be clear, data-driven Vue.js is simply how Vue.js ought to be used. It is a best practice to create clean components that can be reused and extended. It gives you the freedom to swap out components, reuse code, and gives you a starting off point if you ever want to open source parts of your internal Vue.js libary.

Considerations

For large datasets, it would be better to implement some performance optimizations such as pagination/lazy loading. I’ve left the filterByColumns inefficient, and I’ve chosen to specify the columns you want to show, vs excluding the ones you’d want to hide which might be better if you expect your tables to grow and don’t want to touch the code. When considering your architecture, you should also look into the Vue.js community who have built out many components before you. Instead of reinventing the wheel look into contributing to an already popular package! For our scenario it would be good to look at vue-table, vue-tables, or if you’re familiar with the jQuery plugin DataTables, then you might find this interesting. These libraries include many more features that are common with data tables and are almost certainly better than hand rolling a custom library. However, libraries can be overkill in many cases, so the decision is up to you!