Using Dynamic Components And a Pattern I Devised Myself to Create a No Code Web Interface Builder
Matt Anderson
Posted on August 14, 2020
About two years ago I discovered VueJS, around the same time that “no code” solutions began to hit the shelves. I say I discovered Vue, I’d played with Vue, creating the ToDo list app (as you do/ did), but somewhere (I can’t remember where exactly) I encountered the dynamic component and this set me off on a two year journey developing what has now become yakety.co.uk, an interface builder that connects to APIs and cloud services. This article explains how the pattern I created allows for infinitely complex web interfaces to be developed, quickly, easily and using any back-end platform (as it is completely front-end driven).
Quick intro to Dynamic Components
For those of you that aren’t aware of them, may I introduce: Dynamic Components:
<component v-bind:is=”currentTabComponent”></component>
To quote the Vue docs:
Sometimes, it’s useful to dynamically switch between components, like in a tabbed interface.
This was a virtual apple dropping on my head. I saw an opportunity to use this component to create something I’d wanted to create for a while but was beaten to it: A Medium.com style editor. I’m a competitive person by nature so I thought to myself “I’ll still create an editor, only thanks to dynamic components, it will be better!”
I have no early versions to show you so you’ll have to make do with its current incarnation: https://yakety.co.uk/demo-article?edit
So "how does it work" you say? Read on.
1. Components
To build an interface builder the first thing you need are components. I decided to speed things up (he says, two years after starting work on this) by using Buefy, a VueJS component suite that uses styles from the (still quite well known in development circles I think?) Bulma.
You can add Buefy components into any project (that uses VueJS) like this:
<b-input type="is-danger" @input="handleInput"></b-input>
Which was a great speed gain, but I needed to have more (dynamic) control over the way these components look and behave so (out of pure necessity) I created a wrapper component, the template for which looks something like this:
<b-field
:label="items.label"
:message="items.message">
<b-input
:value="items.value"
:name="items.name"
:type="items.subtype"
@input="handleInput">
</b-input>
</b-field>
I named this component s-input
to avoid a clash, then I looked at how I could fetch and set the properties from the server.
I must also mention, I had this idea that all the data required for the page would be fetched all at once and made available to all components by attaching it to the window
object in the browser. That felt like a necessity in order allow the dynamic component to be well, dynamic. I wanted all the components to have access to all the data they may need so that I didn’t box myself into a development corner further down the road.
So here’s what I did (minus the endless trial and error).
2. Server
As with most web applications a page request is made and it hits a controller.
The objective here is to get all the properties required for all the components you wish to display on a page. So using the URI which for the Demo Article example link above is simply demo-article
we run a query that fetches all the component properties for that particular route.
Let’s say we want to display an input and a button. In the most simple example, the query could return the following JSON:
[
{
"is": "s-input",
"type": "text",
"name": "Some input"
},
{
"is": "s-button",
"text": "Click Me"
}
]
Then in a component dedicated to displaying other components (by using the dynamic component), we can loop this data and display our actual components:
<component
v-for="(item, index) in components"
:key="index"
:is="item.is"
:properties="item"
>
</component>
:is="item.is"
tells the dynamic component which component to display.:properties="item"
prop is used to pass the properties to the component, thus determining its behaviour. And of course, the loop is iterating, in this case, over the two JSON ‘blocks’ as I call them, so we have control over a linear flow of components, just like Medium.com's editor and voila:
That is as simple an explanation as I can give to the underlying pattern I used to create interfaces with Yakety. To create more complex interfaces involving columns and heavily nested components would take much explanation and I don’t want this to turn into War and Peace so I’ll stop there for now. If there is sufficient interest then of course I will develop this into a series in which I target specific parts of the pattern that are harder to explain and give you the recipes for developing your own dynamic interfaces, interfaces that are controlled entirely from a database. Which brings me to the last part of the article…
3. Database
The biggest takeaway from what I have achieved here, isn’t the use of dynamic components in VueJS (although that is pivotal to the whole pattern working). The major discovery I made, was to allow for the construction of an entire (or partial) interface using only a database and a bunch of components that, for the most part, are empty shells or vessels. This removes the need for both large (and multiple) templates and logic heavy controllers.
Just think of the possibilities that have opened up (or view Yakety and see to see some of the possibilities I’ve thought of, in action). Here is a summary of things I have considered:
- You can store and therefore manage styles using a database
- You can store and manage behaviour using a database
- You can see in an instant which components exist on a page
- You can easily switch the order and location of a component
- You could theoretically present different components to different users
- You can allow for the creation of content and functionality using a no code solution for non-technical staff
- You can duplicate, update, edit and so on, entire groups of pages or target properties of individual components with ease (you even have the power to do this with a script!) all thanks to your page being defined in a database rather than a file
- The whole pattern is completely platform agnostic. I use VueJS and Laravel. What’s stopping you from using React and ExpressJS?
- Perhaps there are even more benefits that I just haven’t thought of yet (let me know in the comments if you have other ideas about potential uses for the pattern)
I’ll stop there. As I mentioned, if I’ve been overly brief and you would like more detail, just leave a comment and I’ll be happy to expand on anything I’ve said either in a reply or, if the question warrants it, further articles.
I hope you have a good play with Yakety and enjoy using it. I look forward to hearing your thoughts and suggestions.
PS In case you’re wondering, the whole codebase is currently sitting in a private repo. I will eventually get around to making it public and I’ll write some documentation to accompany it.
Posted on August 14, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.