Creating an application using Vuido

Michał Męciński
codeburst
Published in
6 min readSep 4, 2018

--

Vuido is a framework for creating native desktop applications based on Vue.js. Application using Vuido can run on Windows, OS X and Linux, using native GUI components, and don’t require Electron.

I created the first prototype of Vuido a few months ago, simply to find out if it’s possible to use Vue.js in a desktop environment, and to get some early feedback. You can read about this prototype in my previous article. Since then, Vuido received almost 5,000 stars on GitHub and the early prototype turned into a pretty functional and stable version.

However, an important piece of the puzzle was still missing. A framework or library is only as useful as the applications that are using it. Not just example “hello world” applications, but actual applications that provide some value to end users. So I started looking for ideas.

At that time, I was working on LaunchUI, a run-time environment for running GUI-based Node.js applications. In order to create a distributable package for a LaunchUI application, you can run a command line utility which has almost 20 different options, or use an API. I thought that a GUI front-end would make this process much easier, and that’s how the idea of LaunchUI Packager GUI was born.

Designing the user interface

The screenshot above is the final result, but when I started, I didn’t have a clear idea how the user interface should look. What I really like about Vue.js is that you can quickly create and test a prototype of the UI by putting together some HTML and CSS, without writing any code. A similar process can be used with Vuido.

I started by creating a simple template with just the text box, two buttons and a few tabs:

<Window title="LaunchUI Packager GUI" width="800" height="500">
<Box padded>
<Group title="Project" margined>
<Box padded>
<Box horizontal padded>
<TextInput stretchy readonly/>
<Button>Open Project...</Button>
<Button>Save Project</Button>
</Box>
<Text>{{ projectStatus }}</Text>
</Box>
</Group>
<Tab stretchy margined>
<Box label="General">
</Box>
<Box label="Branding">
</Box>
<Box label="Advanced">
</Box>
</Tab>
</Box>
</Window>

Then I started to gradually add more components, inspect the result and make further changes. I repeated this process until the result looked good enough. The simple XML based template syntax, used by Vuido, makes it really easy to make changes, copy and paste pieces of the layout and move things around. It’s as easy as working with HTML and CSS.

Updating controls

When the application is started, most of the controls have to be initially disabled, until a project is loaded or created. In traditional, imperative code, you would have to write something like this:

this.packageNameTextInput.enabled = false;
this.packageVersionTextInput.enabled = false;
// ... and so on

Because Vuido is based on Vue.js, I could simply bind the enabled attribute of each control to a property of the window instance, like this:

<TextInput label="Package name:" v-bind:enabled="isEnabled"/>
<TextInput label="Package version:" v-bind:enabled="isEnabled"/>
// ... and so on

Then I could simply enable or disable all controls at once by toggling the isEnabled property.

Later, when it turned out that the controls should also be disabled while a build is running, I changed the isEnabled property to a computed property, defined like this:

isEnabled() {
return this.dirPath != '' && !this.isBuilding;
}

This way, I could simplify the state of the application and reduce the numer of possible state combinations. This makes it easier to avoid mistakes; for example I don’t have to remember to modify the isEnabled property when the build ends. I can just toggle the isBuilding property and the state of other properties is automatically updated. So computed properties are a very useful feature of both Vue.js and Vuido.

Binding control values to data properties is also very simple with Vuido, thanks to the v-model directive known from Vue.js. So instead of having to write this code to pass data to controls:

this.packageNameTextInput.value = this.options.name;
this.packageVersionTextInput.value = this.version;
// ... and so on

and the corresponding code to do the opposite, I could simply add the v-model directive, like this:

<TextInput label="Package name:" v-model="options.name"/>
<TextInput label="Package version:" v-bind:enabled="isEnabled"/>
// ... and so on

Once you get used to such declarative style of programming, you realize that it makes things easier. It doesn’t really matter if it’s a web application or a desktop application, because the basic principles are the same.

Reusable components

If you look at the screenshot of LaunchUI Packager GUI, you can notice a few common patterns:

  • Some text boxes have a “Choose…” button next to them, which opens a file selector dialog.
  • Each tab consists of a few Group boxes which contain nested Form layouts.

During the prototyping, I simply copied and pasted these common elements, but when I started cleaning up the code, I decided to replace them with reusable components. Vue.js makes it very easy to create such components and the same can be done in Vuido.

The FormGroup component looks like this:

<template>
<Group v-bind:title="title" margined>
<Form padded>
<slot/>
</Form>
</Group>
</template>
<script>
export default {
props: {
title: String
}
}
</script>

It has a very simple template and just one property, but it allowed me to greatly simplify the template of the main window and remove a lot of duplication.

The FileInput control is just a bit more complicated:

<template>
<Box v-bind:label="label" horizontal padded>
<TextInput stretchy v-bind:value="value"
v-bind:enabled="enabled" v-on:input="input"/>
<Button v-bind:enabled="enabled"
v-on:click="choose">Choose...</Button>
</Box>
</template>
<script>
export default {
props: {
label: String,
value: String,
enabled: {
type: Boolean,
default: true
},
dirPath: String
},
methods: {
input( value ) {
this.$emit( 'input', value );
},
choose() {
// ...
}
}
}
</script>

The template is just a horizontal box layout with a TextInput and a Button. The component has a value property and emits the input event whenever its value changes, so it can be used with the v-model directive, just like the regular TextInput control. That made it very easy to replace the TextInput controls with FileInput components where necessary, without having to make any other changes in the main window.

Custom components is one of the most powerful feature of Vue.js which also makes creating desktop applications with Vuido much easier.

Conclusions

Creating the LaunchUI Packager GUI was easier that I expected. I was able to take advantage of many benefits of Vue.js, including rapid UI prototyping, declarative data binding and reusable components. So the reactive, component-based paradigms, designed to make web development easier, turned out to work really well in a desktop application. It’s not a surprise, because the whole reason these web framework evolved was that web applications became as complex as desktop applications.

I proved that Vuido works, but that wasn’t the only benefit of creating the LaunchUI Packager GUI application. While working on it, I found some bugs in Vuido which would be hard to find in a simple “hello world” project. The recently released version 2.0 of Vuido not only fixes them, but also has a full suite of unit tests, so the stability of the framework has greatly improved since the first release. I also extended the API of Vuido to fill some gaps and make some things easier.

Over the last decade I used a lot of different libraries and frameworks for developing desktop applications, including MFC, .NET, Qt and Electron. They all have their strengths and weaknesses, and the same can be said about Vuido. At the moment it’s certainly missing some features useful for building very large and complex applications. However, it turned out to be perfectly suitable for the task that I tried to accomplish. And the possibilities of Vuido are still growing.

A new feature in version 0.2 of Vuido is the Area widget, which supports drawing 2D graphics and handling mouse and keyboard input. This opens the possibility to implement a lot of interesting things, including custom widgets, data visualizations and even simple games. The latest Alpha 4 release of libui includes a new table widget, which will also be implemented in a future version of Vuido. Other features are also planned, including OpenGL support, tree widgets, printing, and many more, so Vuido has a chance to become a really interesting platform for developing cross-platform desktop applications.

✉️ Subscribe to CodeBurst’s once-weekly Email Blast, 🐦 Follow CodeBurst on Twitter, view 🗺️ The 2018 Web Developer Roadmap, and 🕸️ Learn Full Stack Web Development.

--

--