Switching pages using Vue3 routing with uibuilder
This is an example about using Vue3 routing mechanism on uibuilder
v.5.1.1, with the new uibuilder.iife
library.
The example is aimed to show 2 different scenarios:
- changing the route view from the app, by clicking on the buttons;
- changing the route view from a Node Red flow, by injecting a message with a
topic
ofrouter/switch
and the route path inmsg.payload
. This can be useful to switch the Dashboard on a specific page when an important event happens in the flows.
The route files (.vue) are stored in the folder: ./routes/
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Router test - Node-RED uibuilder</title>
<meta name="description" content="Node-RED uibuilder - Router test">
<link type="text/css" rel="stylesheet" href="./index.css" media="all">
</head>
<body>
<div id="my-app" style="text-align:center">
<nav>
<router-link to='/'><button style="margin-right:3em">Home</button></router-link>
<router-link to='/contacts'><button>Contacts</button></router-link>
</nav>
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" />
</keep-alive>
</router-view>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.prod.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue3-sfc-loader/dist/vue3-sfc-loader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue-router.global.js"></script>
<!-- #region Supporting Scripts. These MUST be in the right order. Note no leading / -->
<script src="../uibuilder/uibuilder.iife.min.js"></script>
<script src="./index.js"></script>
</body>
</html>
index.js
'use strict'
const { createApp, ref } = Vue
const options = {
moduleCache: {
vue: Vue,
vueRouter: VueRouter
},
async getFile(url) {
const res = await fetch(url);
if (!res.ok)
throw Object.assign(new Error(res.statusText + ' ' + url), { res });
return {
getContentData: asBinary => asBinary ? res.arrayBuffer() : res.text(),
}
},
addStyle(textContent) {
const style = Object.assign(document.createElement('style'), { textContent });
const ref = document.head.getElementsByTagName('style')[0] || null;
document.head.insertBefore(style, ref);
},
}
const { loadModule } = window['vue3-sfc-loader'];
window.asyncVue = sfc => Vue.defineAsyncComponent(() => loadModule('./routes/' + sfc + '.vue', options))
window.dynamicVue = com => ({
name: 'DynamicWrapper',
template: `<component :is="comp"></component>`,
computed: {
comp() {
const com = this.com;
return asyncVue(com);
}
},
data() {
return { com }
}
})
const routes = [
{ path: "/", name: 'home', component: dynamicVue('home'), meta: { KeepAlive: true } },
{ path: "/contacts", component: dynamicVue('contacts'), meta: { KeepAlive: true } },
];
const router = VueRouter.createRouter({
history: VueRouter.createWebHashHistory(),
routes
})
const app = Vue.createApp({
data() {
return {
}
},
methods: {
switchToRoute(rt) {
this.$router.push(rt)
}
},
mounted: function () {
uibuilder.onChange('msg', (msg) => {
if (msg.topic === "router/switch") { this.switchToRoute(msg.payload); }
})
},
})
app.use(router)
app.mount('#my-app')
home.vue
<template>
<h4> This is Home Page</h4>
<p class="blueclass">Router view</p>
<p>{{ local }}</p>
</template>
<script>
export default {
data() {
return {
local: "This variable is local to the Home view"
}
},
}
</script>
<style scoped>
.blueclass {
color: blue;
}
</style>
contacts.vue
<template>
<h4> This is the Contacts Page</h4>
<p class="greenclass">Router view</p>
<p>{{local}}</p>
</template>
<script>
export default {
data() {
return {
local: "This variable is local to the Contacts view"
}
}
}
</script>
<style scoped>
.greenclass {
color: green;
}
</style>
[{"id":"203435ce1f57e6cd","type":"inject","z":"bfa02725ef845ede","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"router/switch","payload":"/","payloadType":"str","x":274,"y":460,"wires":[["296594508ac2e284"]]},{"id":"81ff8800034014d3","type":"inject","z":"bfa02725ef845ede","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"router/switch","payload":"/contacts","payloadType":"str","x":250,"y":540,"wires":[["296594508ac2e284"]]},{"id":"296594508ac2e284","type":"uibuilder","z":"bfa02725ef845ede","name":"","topic":"","url":"router-test","fwdInMessages":false,"allowScripts":false,"allowStyles":false,"copyIndex":true,"templateFolder":"blank","extTemplate":"","showfolder":false,"reload":false,"sourceFolder":"src","deployedVersion":"5.1.1","x":470,"y":489,"wires":[[],[]]}]