FlowFuse / node-red-dashboard

https://dashboard.flowfuse.com
Apache License 2.0
159 stars 35 forks source link

Importing external vue components #707

Open gidoUninova opened 3 months ago

gidoUninova commented 3 months ago

Hi all,

I am working with nodered since 2018 and I have several projects implemented with it. I am now updating some implementations in order to use dashboard v2.0 instead of the dashboard v1. In this sense I would like to know how I can import external vue components within the ui-template. To be more specific I have a complex json object and I need to show it as a tree. Googling a little I found this:

https://github.com/zdy1988/vue-jstree?tab=readme-ov-file

I would like to know how can I use this component (vue-jstree) in my ui-template. I was able to wrap a jstree jquery plugin into my ui-template however I found that it is not a good practice. Moreover I have some troubles in listening events from jquery to vue.

Can you help me on this (using external vue components in ui-template)?

thank you in advance.

giovanni

mreis1986 commented 3 months ago

i really need this feature asap on my project too

joepavitt commented 3 months ago

i really need this feature asap on my project too

Just to clarify, you need the tree specifically, or the general ability to load external vue components?

joepavitt commented 3 months ago

Will mention that the specific plugin you've linked to is 6 years old, and only for Vue 2 - would be unlikely to work in Vue 3 which is what we're using.

Vuetify have made their "Treeview" component available in preview: https://vuetifyjs.com/en/components/treeview/#installation so that will not be far away, and may even work already with the relevant import statement inside the ui-template.

NorbNorb commented 3 months ago

I'd also like to import Vue components like this:

<script>
import { MyComponent } from 'vue';
...

Currently I get the following error:

errorCaptured SyntaxError: Cannot use import statement outside a module

gidoUninova commented 3 months ago

i really need this feature asap on my project too

Just to clarify, you need the tree specifically, or the general ability to load external vue components?

Dera Joe, thank you for the answer. BTW I need a general capability to import vue components (third party). The tree is only an example to show you what I would like to have. Moreover, I noticed last week the vuetify components roadmap and specifically that a treeview will be available in June.

joepavitt commented 3 months ago

Thanks, the ability to import using import is going to be very very tricky, if not impossible. We have no way of installing, at runtime, into the Vue app build. UI Template uses an acorn parser which means that the import statements cannot be run. We'd have no way of telling Vue what libraries to install, etc. ahead of import.

The workaround for including third-party JS is detailed here - but isn't trivial to convert this to being able to include external Vue packages.

Absolutely open to ideas on how it could be done though, and won't rule out any options.

NorbNorb commented 3 months ago

The mentioned workaround only works with a working internet connection, right? That’s not something I will have in my setup :(

joepavitt commented 3 months ago

Correct - I don't, currently, know of any alternatives unfortunately. @totallyinformation - how do you handle this with UI Builder?

NorbNorb commented 3 months ago

Can I manually install the libraries I need? Like putting the files on disk?

joepavitt commented 3 months ago

Can I manually install the libraries I need? Like putting the files on disk?

The challenge here is how to install them onto disk such that Node-RED could access them, @Steve-Mcl will have a bit more insight into the Node-RED workflow here.

TotallyInformation commented 3 months ago

UIBUILDER doesn't need to do any complex JS parsing. Though it does now allow conversion from low-code config JSON to HTML in Node-RED (via the uib-html node), that simply uses JSDom and the ui.js library which the uibuilder client library also uses.

Any passing of JS from Node-RED to the front-end results in a native browser parse of the input text to JS. There are a couple of different methods used depending on the need, here is a simple example:

    /** Attach a new text script to the end of HEAD synchronously
     * @param {string} textFn The text to be loaded as a script
     */
    loadScriptTxt(textFn) {
        const newScript = this.document.createElement('script')
        newScript.async = false
        newScript.textContent = textFn
        this.document.head.appendChild(newScript)
    }

This executes the script on load.


However, I think that is a red-herring. It isn't JavaScript you want when trying to incorporate most Vue components since most components are not released with a built JS version I don't believe, most are released as .vue files aren't they? (they were last time I looked).

This page in the UIBUILDER WIKI shows you how to dynamically load Vue components without a build step which is what I think you may be looking for?

https://github.com/TotallyInformation/node-red-contrib-uibuilder/wiki/Load-Vue-(v2-or-v3)-components-without-a-build-step-(modern-browsers-only)

postlund commented 2 weeks ago

I'm kind of in the same boat as well right now, dealing with #676. I intend to try apexcharts and see if I can gain better results, at least until we have a more permanent solution (again, #676). Just wanted to leave a small tip here. You can serve arbitrary files directly from nodered using the httpStatic setting, then just place the minified javascript file there. I have this:

{
    // ...
    httpStatic: '/data/static',
    // ...
}

In my case /data is a docker volume pointing to my nodered configuration. I then just create a directory called static, put my file in there and include it like so:

<script src="/apexcharts.js"></script>

You need to check that it has been loaded as well:

<script>
let interval = setInterval(() => {
    if (window.ApexCharts) {
        init();
        clearInterval(interval);
    }
}, 100);
</script>

Still have a long way to go until I have something useful working, but this at least gives my apexcharts locally, without any reliance on the a network connection.