Create beautiful Apps Script add-ons with Vuetify and Vue.js

The idea of ‘reactive programming’ has been around for many years, but frameworks such as React, Vue and so on have moved it into the mainstream.  In these frameworks the idea is that changes in data streams are observed,  processed and  propagated into the app model and view. Dealing with asynchronicity and rendering them has always been complex, but these frameworks are designed to make the flow of data through an app less problematic.
In these series of articles. we’ll be creating a reactive app in an Apps Script for htmlservice context using a mash up of each of these, and a few others too.

  • Vue.js – the framework
  • Vuetify – a material design framwork for use with Vue.js
  • Vuex – a state management pattern adnd library for Vue.js
  • Qottle – for managing asynchronous queues to keep the client synchronized with the spreadsheet it services
  • TimeSimmer – for simulating speeded up real time
  • Fiddler – for abstracting sheet data
  • Keystore – for managing whitelist and provoking server functions from htmnlservice
  • Include – for organizing add-on files
  • TabVisibility – for handling the add-on being in focus and adjust behavior

 

Vue.js and Htmlservice

The normal mode when developing anything but the most trivial app with app is to use Vue-cli, develop the app in Node.js, then bundle the result to run in browser mode. In Apps Script, we could do this using webpack or clasp , and indeed this is how I normally develop in Vue.js (in fact the majority of my  JavaScript development is done on Node.js) . However, most Apps Script developers still develop in the Apps Script IDE, and just this week (December 2020), there’s a modernized version of the IDE released, which means that sticking with the Apps Script IDE  is often more practical. However, it’s quite tricky to organize your Vue.js code with multiple components without using vue-cli, but one of the first topics I’ll cover is exactly how to do that.

 

The template app

vue.js template for apps script

 

how to get it

The full code is on Github, and discussed in the following pages, and there’s a demo spreadsheet you can clone to play with it, or you can clone the script from here.

Here’s the basic view in the sidebar. The idea is that you can use this bare bones template to create your own without having to worry too much about re-inventing the structure. It’s not  intended to be a serious or useful add-on in itself, but it will demonstrate many of the elements and structures needed to build one.

 

Vue.js components

Vue.js is a component based framework. Writing reusable components is the name of the game. You’ll see as we go through the code that the components are rather small, resusable, and contain little logic.

Almost all the control happens in the Vuex store. Because the htmlservice pattern is not modular, we have to use a special technique to keep components discrete and avoid spaghetti.

 

Vuex store

The Vuex store is used for state management and store reactivity ensures that each component has access to the model data. In my pattern, the store is the heart of the app which not only manages the state, but also contains global info such as the Vue template definitions themselves. To see more about Vuex implementation, see Improve Vue.js Apps Script add-ons with a Vuex store

 

Qottle

Keeping the sidebar up to date in an add-on when the data is changing is challenging, as there is no synchronization between the current spreadsheet content, and the data in the client side add-on. One technique I’ve used a lot is continous polling.

In this pattern, I’ve improved that technique using the queuing and rate limiting capabilities of  qottle  to poll in a non- intrusive way, along with caching on the server side to minimize access to the parent sheet data, fiddler to normalize sheet data, and a system of fingerprints to only transfer data if anything has actually changed.

 

TimeSimmer

This demo app cycles through a weekly schedule of flights changing their status over time. TimeSimmer gives a way providing adjustable time so we can speed up or slow down the action.

 

Fiddler

This is a functional approach to dealing with and manipulating sheet data. It’s not a great idea for the client side to have to worry too much about the structure of a sheet. Fiddler translates the physical layout of the sheet into stable properties that are of interest to the client side app and also keeps track of any changes that are made server side, dumping the updates where relevant

 

KeyStore and Provoke from add-ons

google.script.run is not really a wonderful way of provoking server side functions from the client. You end up with too much stuff in the global space, you can’t call things in namespaces (now even harder with V8) or libraries, so you end up with a mess.

Much better to whitelist everything you want to run in a single keystore then use promise/async style calls to manage anything on the server from the client. See Apps Script V8: Provoke server side code from add-ons and htmlservice for more details.

 

Include

It can be tricky to include the right stuff in the right order, and it becomes even more so with modules, and imports from npm. Include will help to organize and bundle your source code for input to htmlservice execution.

More detail on the template

The full code is on Github, and discussed in the following pages, and there’s a demo spreadsheet you can clone to play with it, or you can clone the script from here.

You can navigate through further details on the template below