Uibuilder: Component Design + Example Components

Hi all, this topic is to capture ideas and decisions regarding the design of a VueJS component standard for uibuilder.

uibuilder VueJS components will be standard pieces of front-end code with an agreed msg schema for communications from/to Node-RED. They will be the uibuilder equivalent of Dashboard widgets. However, where those send the code as well as the data from Node-RED to the front-end, uibuilder components will only send data since the code is developed using standard web development methods.

Here are my starter requirements for uibuilder VueJS components - everything is open for discussion though so if you disagree, please chip in and explain why and what might be better:

  1. Each component (or component set) must be installable via npm (e.g. using the uibuilder library manager or manual install into the userDir folder)

  2. Components npm modules should be named node-red-contrib-uib-xxxxx - the components themselves should be named in line with VueJS naming conventions and should clearly identify what they do in the name.

    I'm actually not sure about this one and would welcome input from Nick and Dave in particular as to whether they would prefer a different naming convention. After all, these components could be used outside of Node-RED. However, "uibuilder" is a term also used in other modules not related to us.

  3. Component npm modules should have the "uibuilder" tag.

  4. Component npm modules should NOT have a "node-red" tag (so that they don't confusingly appear in the Node-RED flows library) - after all, these are not Node-RED extensions and could be used outside of Node-RED.

    The exception to this would be where a component includes a new Node-RED Node. This should not be a common requirement.

  5. Component npm modules MUST have a peer dependency of "node-red-contrib-uibuilder" listed in their package.json files.

  6. Component npm modules should identify the versions of VueJS they will work with.

  7. uibuilder components MUST be usable with or without a build step.

  8. Any JavaScript must be self isolating (wrapped in an anonymous, self-executing function).

  9. Components must have suitable documentation including a schema description of the msg (or msgs) required.

  10. Components should be listed in the component index (to be created). This index may in the future auto-discover components based on the agreed component naming and a "uibuilder" tag in the npm module.

  11. Components should not assume that inputs are in any way correct or safe.

  12. Components must take note of the uibuilder v3 proposed msg.auth schema that will be used for exchange of authentication/authorisation information.

The critical part of any uibuilder component will be the schema that describes how communications between Node-RED and your front-end happen and in what format.

In general, uibuilder VueJS components should not need a new Node-RED Node since all that is required is to send an appropriate msg to the front-end. It is currently expected that all communication happens via the uibuilder node instance. If we come across a situation that needs something different, we will need to have a separate discussion since it is possible that changes to uibuilder itself might be needed.

1 Like

I have been working on components via a http-in/response node and serving the component via template nodes when using vuejs.

Meaning: the index.js requests components that are being served via node-red/templates, no dependencies on external files and everything can be managed within node-red (a template node is a component)

In short, i am not in favor of all these stringent rules if it takes the current functionality away (ie. force vuejs), i use uibuilder also with vanilla js for example.

Hi,

Sorry, I should have made that more clear in my first post. There is no intention to take anything away from uibuilder. You will still be able to use any framework you like (or no framework at all).

Indeed, I'd be delighted to start a discussion about components for other frameworks too as the same principles can apply.

Also, the availability of components won't make any difference to what you are doing other than to possibly identify some communications standards that might be helpful to you in the future.

To clarify then. uibuilder components are designed to make things easier for Node-RED users who might not have the knowledge to create complex front-end user interfaces. They are optional extensions to how uibuilder can be used, making the ui build easier. In reality, they are simply standard bits of front-end code with an agreed communications schema that can be reused wherever and whenever you like. Indeed, you could use them outside of Node-RED as well since I anticipate that most of them will be standard VueJS components.

I like this as another option! It would be great to see this written up somewhere. Either in the flows library or as a WIKI entry on the uibuilder GitHub maybe?

How are you managing the request in your front-end code? Would it benefit from being added as a standard function in uibuilderfe?

How are you managing the request in your front-end code? Would it benefit from being added as a standard function in uibuilderfe?

httpVueLoader requires a .vue file, basic idea is like:

'use strict';
var app1 = new Vue({
	el: '#app',
	components: {
		chart: httpVueLoader('http://10.0.0.6:1880/components/chart.vue'),
		pulldown: httpVueLoader('http://10.0.0.6:1880/components/pulldown.vue'),
	},
	data: {
		msg: '',
	},
	computed: {},
	methods: {},

	mounted: function () {
		uibuilder.start();
		var vueApp = this;

		uibuilder.onChange('msg', function (msg) {
			vueApp.msg = msg;
		});

	},
});

Where http://10.0.0.6:1880/components/chart.vue will be served via the http-in/template/response nodes
For the http-in node I use:

msg.request.param will become: chart and pulldown that can be used in a switch node, return the component from a template node.

I guess this is something that uibuilder could be able to serve somehow as well - like; if .vue request, send it (optionally) to one of the outputs of the uibuilder node, where one can capture it. But how to inject it back into uibuilder i dont know, as it needs to be served back somehow.

I could write up a wiki, but not sure about structure.

Ah, OK, I think that is already in the WIKI.

Ok if it is great, I doubt it however, as it is not described how to serve dynamic files from within node-red; ie. template nodes. It works great and don't have to maintain files outside node-red.

Your original topic is about component design, which you can easily put in a template node like this.

True. If you can add something to cover how you are delivering that from Node-RED, I can always tidy it up later so don't worry about the style.

I now have an example component module on GitHub if anyone wants to try it.

To be honest, I started this some while back but only just got round to uploading it - I can't remember the current status of the components and the documentation may still be a bit weak.

Anyway, just to let people know that I'll be using this module to try and create some VueJS components for use with uibuilder.

Read the README carefully for installation and usage.

I've pushed some updates as well so that the gauge component now works - far from complete but it does work.

Another update pushed.

See the examples for the gauge component - you will see the first examples of pushing data direct to the component so that you don't have to do anything in your HTML (eventually not in your js either as this will be folded into the uibuilderfe library).

All you need to do is set an ID on each component instance and then send the right data format through to the front-end.

The HTML can be as simple as:

<gauge ref="gauge1" />

This all looks incredibly interesting, however I am not sure how I test out what you have built?

Also, given my learning experience with uibuilder, I'm wondering how much benefit these nodes will provide if you know how to write the code for the component in the first place. I guess it will work really well for more complex components, right?

Well the idea is to provide components that will mirror some of those in Node-RED's Dashboard. So that you can quickly drop in a component reference and start sending data to it straight away.

At the moment, whenever you look at a Vue component, you have to work out how it has been packaged, what it's props are and how to use it. Fine if you are only using a few and are familiar with Vue. Not so good otherwise. While the uibuilder WIKI has some components documented, it is still daunting to set up for many people.

It gets worse if you want multiple components and/or multiple copies (instances) of components (e.g. multiple gauges on a page). Currently you have to hand-craft front-end javascript code to unpick data that is sent through and work out how to update the correct instance.

Once I (and hopefully others) start wrapping components for use in this way, you will have a very simple, standardised way to send data through to multiple component instances without any code required. There will also be standardised ways of getting data back to Node-RED again - have a look at the gauge .vue code for example and you will see an optional click handler that sends key event data back to Node-RED automatically when you click on the gauge (if you've turned on the flag).

What's more, there will be instructions on how to build new components that work in the same way so anyone with some Vue skills can write their own or wrap existing components.

And the icing on the cake will be a command that you can send from Node-RED that will return a msg containing the data schema and a link to the components documentation. So taking away any confusion about how to send data to the component.

Data-driven UI's are a real interest of mine and have been for years and I'm quite excited about this. I've been trying to work through the possibilities of how to make uibuilder easier for people to use and this feels like a real step forwards.


Testing does require some commitment at the moment. You need to manually install the extras node from GitHub to your userDir folder, restart Node-RED and then copy the html and js from the example files into a uibuilder instance.

The gauge component is the easiest one and the only one with the start of the standardised comms built in (currently in the index.js file).

Try adding a second gauge to the page with a different ref id and send data to both. I'll update the repo shortly with an example flow that you can import as well.

1 Like

Much clearer, thank you!

I'll try and carve out some time to test what you've done. It's sounds like the start of a beautiful thing!

The updates are loaded. Here is the example web page.

While this page uses some extra HTML, the minimal is: <gauge ref="gauge1" /> nothing else needed.

A picture says a thousand words.

This will be cool. Just need to get people behind it.

Wish I was better at Vue so I could build a component.... I guess a goal for next year... Ha ha!!!

Rome wasn't built in a day :sunglasses:

Have a look at the gauge .vue file, you might be surprised just how simple it is. Even with the crud that is currently in it as I experiment with things.

I can tell you that I am far from being any kind of Vue expert. I just about understand the basics.