Skip to content

Instantly share code, notes, and snippets.

@fmarzocca
Last active July 6, 2022 12:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fmarzocca/f930d699a09ed0ab52a2157570db5d71 to your computer and use it in GitHub Desktop.
Save fmarzocca/f930d699a09ed0ab52a2157570db5d71 to your computer and use it in GitHub Desktop.
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 of router/switch and the route path in msg.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/vue-router@4.0.3/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":[[],[]]}]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment