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
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