Hi,
As part of the next step I've been playing with the uibuilder + VueJS.
Last step (well, current last step) before I start to create new UI I wanted to divide my (future) frontend in VueJs components. Well........ Let's just say I'm stuck there for a while now......
To make it short, I've been trying to make dynamic frontend like @UnborN just without compiling like @JM_Energy here: uibuilder-vue-router-without-compiling
So, ATM I just want to make a full navigation without any props or keys - that I'll try to do later.
Node-RED version: v2.2.2
Node.js version: v14.18.0
Windows_NT 10.0.19043 x64 LE
"dependencies": {
"bootstrap": "^5.1.3",
"bootstrap-vue": "^2.21.2",
"http-vue-loader": "^1.4.2",
"normalize.css": "^8.0.1",
"vue": "^2.6.14",
"vue-router": "^3.5.3",
"vuex": "^3.6.2"
}
I've tried to run every example from the forum and github I could find, but I think the problem might be somewhat greater...
I have 2 main problems:
- vue component's can't load from any other folder than
src
Errors:
I really don't understand, I've been trying to load the file using httpVueLoader('./views/page1.vue')
- When I load the file from src folder, the template content is not displayed at all - only the root navbar vue file.
I know it loaded becase I see it in the console message. Also, I can only load each file once, after this it won't work anymore.
Any help, info, link would be much appreciated.
code
index.html
<!doctype html><html lang="en"><head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes">
<title>http-vue-loader/VueJS Example - Node-RED UI Builder</title>
<meta name="description" content="Node-RED UI Builder - http-vue-loader/VueJS Example">
<link rel="icon" href="./images/node-blue.ico">
<link type="text/css" rel="stylesheet" href="../uibuilder/vendor/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.css" />
<link rel="stylesheet" href="./index.css" media="all">
</head><body>
<div id="app">
<b-container id="app_container">
<h1>
Example of trying new things :)
</h1>
<navbar :greeting="myGreeting" :who="myWho"></navbar>
</b-container>
</div>
<script src="../uibuilder/vendor/socket.io/socket.io.js"></script>
<!-- Use vue.min.js for production use -->
<script src="../uibuilder/vendor/vue/dist/vue.js"></script>
<script src="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.js"></script>
<script src="../uibuilder/vendor/http-vue-loader/src/httpVueLoader.js"></script>
<script src="../uibuilder/vendor/vue-router/dist/vue-router.js"></script>
<script src="./uibuilderfe.min.js"></script> <!-- //prod version -->
<script src="./index.js"></script>
</body></html>
navbar.vue
<template>
<div>
<b-row>
<b-col class="hello" cols="12">
{{greeting}} {{who}}
</b-col>
<slot>
Default slot content, replace with your own text between the component tags.
See the <a href="https://vuejs.org/v2/guide/components-slots.html" target="_blank">VueJS documentation for slots</a> for more information.
</slot>
</b-row>
<b-navbar type="dark" variant="dark">
<b-navbar-nav>
<router-link to="/navbar">BACK</router-link>
<b-nav-item to="/navbar/page1" exact :active="$route.name == 'page1'">Page 1</b-nav-item>
<b-nav-item to="/navbar/page2" exact :active="$route.name == 'page2'">Page 2</b-nav-item>
<router-link :to="{name: 'page1'}" >Go to Page 11</router-link>
<router-link :to="{name: 'page2'}" >Go to Page 22</router-link>
<router-link to="/navbar/page1">page111</router-link>
<router-link to="/navbar/page2">page222</router-link>
</b-navbar-nav>
</b-navbar>
</div>
</template>
<script>
module.exports = {
/** Allow greeting and who to be passed as parameters but provide defaults
* @see https://vuejs.org/v2/guide/components-props.html#Prop-Validation
*/
props: {
'greeting': {type: String, default: 'Hello'},
'who': {type: String, default: 'World'},
},
/** Any data must be wrapped in a fn to isolate it in case this component is used multiple times */
data: function() { return {
}}
}
</script>
<style scoped>
.hello {
background-color: #ffe;
font-size: 2rem;
text-align: center;
}
</style>
page2.vue
<template>
<div>
<b-row>
<h1>PAGE 2</h1>
<b-col class="hello" cols="12">
{{greeting}} {{who}}
</b-col>
<slot>
See the <a href="https://vuejs.org/v2/guide/components-slots.html" target="_blank">VueJS documentation for slots</a> for more information.
</slot>
</b-row>
<b-navbar type="dark" variant="dark">
<b-navbar-nav>
<router-link to="/navbar">BACK</router-link>
<b-nav-item to="/page1" exact :active="$route.name == 'page1'">Page 1</b-nav-item>
<b-nav-item to="/page2" exact :active="$route.name == 'page2'">Page 2</b-nav-item>
<router-link :to="{name: 'page1'}" >Go to Page 11</router-link>
<router-link :to="{name: 'page2'}" >Go to Page 22</router-link>
<router-link to="/navbar/page1">page111</router-link>
<router-link to="/navbar/page2">page222</router-link>
</b-navbar-nav>
</b-navbar>
</div>
</template>
<script>
console.log('wow kurac2')
module.exports = {
/** Allow greeting and who to be passed as parameters but provide defaults
* @see https://vuejs.org/v2/guide/components-props.html#Prop-Validation
*/
props: {
'greeting': {type: String, default: 'Hello'},
'who': {type: String, default: 'World'},
},
/** Any data must be wrapped in a fn to isolate it in case this component is used multiple times */
data: function() { return {
}}
}
</script>
page1.vue
<template>
<div>
<b-row>
<h1>PAGE 1</h1>
<b-col class="hello" cols="12">
{{greeting}} {{who}}
</b-col>
<slot>
See the <a href="https://vuejs.org/v2/guide/components-slots.html" target="_blank">VueJS documentation for slots</a> for more information.
</slot>
</b-row>
<b-navbar type="dark" variant="light">
<b-navbar-nav>
<router-link to="/navbar">BACK</router-link>
<b-nav-item to="/page1" exact :active="$route.name == 'page1'">Page 1</b-nav-item>
<b-nav-item to="/page2" exact :active="$route.name == 'page2'">Page 2</b-nav-item>
<router-link :to="{name: 'page1'}" >Go to Page 11</router-link>
<router-link :to="{name: 'page2'}" >Go to Page 22</router-link>
<router-link to="/navbar/page1">page111</router-link>
<router-link to="/navbar/page2">page222</router-link>
<router-link to="/navbar">BACK</router-link>
</b-navbar-nav>
</b-navbar>
</div>
</template>
<script>
console.log('wow kurac')
module.exports = {
/** Allow greeting and who to be passed as parameters but provide defaults
* @see https://vuejs.org/v2/guide/components-props.html#Prop-Validation
*/
props: {
'greeting': {type: String, default: 'Hello'},
'who': {type: String, default: 'World'},
},
/** Any data must be wrapped in a fn to isolate it in case this component is used multiple times */
data: function() { return {
}}
}
</script>
index.js
'use strict'
const navbar = httpVueLoader('navbar.vue');
const page2 = httpVueLoader('page2.vue');
const routeDefs = [
{
path: '/navbar',
name: 'navbar',
components: navbar,
children: [
{
path: '/navbar/page1',
name: 'page1',
component: httpVueLoader('./views/page1.vue')
},
{
path: '/navbar/page2',
name: 'page2',
component: page2
//component: httpVueLoader('page2.vue')
}
],
props: {
string:"From Index",
number: 33,
value: "ochenta"
}
}
]
// eslint-disable-next-line no-unused-vars
var app1 = new Vue({
el: '#app',
//router,
router: new VueRouter({routes: routeDefs}),
/** Load external component files
* Make sure there is no leading / in the name
* To load from the common folder use like: 'common/component-name.vue' */
components: {
'navbar':navbar
}, // --- End of components --- //
data: {
myGreeting: 'Hi there',
myWho: 'oh wise one!',
//myRoutes: routeDefs, // redefine here so we can push it down
//myProps: properties,
}, // --- End of data --- //
computed: {
}, // --- End of computed --- //
methods: {
}, // --- End of methods --- //
// Available hooks: init,mounted,updated,destroyed
mounted: function(){
/** **REQUIRED** Start uibuilder comms with Node-RED @since v2.0.0-dev3
* Pass the namespace and ioPath variables if hosting page is not in the instance root folder
* e.g. If you get continual `uibuilderfe:ioSetup: SOCKET CONNECT ERROR` error messages.
* e.g. uibuilder.start('/nr/uib', '/nr/uibuilder/vendor/socket.io') // change to use your paths/names
*/
uibuilder.start()
var vueApp = this
// Process new messages from Node-RED
uibuilder.onChange('msg', function (msg) {
// We are assuming that msg.payload is an number between zero and 10
// Change value
if (msg.payload.hasOwnProperty('greeting')) vueApp.myGreeting = msg.payload.greeting
if (msg.payload.hasOwnProperty('who')) vueApp.myWho = msg.payload.who
//console.log(msg)
})
} // --- End of mounted hook --- //
//router: new VueRouter(router)
}) // --- End of app1 --- //
// EOF