Vue router and javalin-vue
See original GitHub issueAfter a month, and two apps later my first experience of Javalin, I ran into a problem I can’t figure out.
I used JavalinVue to support my dashboard page. I have a dashboard with a fixed top navbar and an also fixed (for the sake of the example) and always visible right sidebar. When I open the dashboard, it displays as it should.
However, when I click on the brand (navigating to /ownerhome
) or the menu item (navigating to /services
), it doesn’t display (replace the router-view) to the given component. Additionally, while the navbar remains, the sidebar disappears.
What I would like to achieve: keep the top navbar and the sidebar (don’t reload them, because that’s costly) in spot and replace only the content. I tried a lot of options, but can’t find the reason. The console shows that the router.beforeEach is called and the url is changed.
layout.html
<html>
<head>
<title>[[Application.name]]</title>
<meta charset="utf8">
<script src="/webjars/vue/2.6.10/dist/vue.min.js"></script>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Titillium+Web">
<link rel="stylesheet"
href="https://maxst.icons8.com/vue-static/landings/line-awesome/line-awesome/1.3.0/css/line-awesome.min.css">
<link rel="shortcut icon" href="/favicon.png" type="image/x-icon"/>
<link type="text/css" rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootswatch/4.5.2/cyborg/bootstrap.min.css"/>
<script src="https://unpkg.com/bootstrap-vue@2.18.0/dist/bootstrap-vue.min.js"></script>
<script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-vue/2.18.0/bootstrap-vue.min.css"
integrity="sha512-oqSSCKWeQcVs+9Hek1tZlj8hMlLhDNI+NUmm56nBCsO4OLE8dyDpaUA/b2zGi+M9SML0xwGtk22ozH2qyqKipg=="
crossorigin="anonymous"/>
@componentRegistration
</head>
<body>
<main id="main-vue" v-cloak>
@routeComponent
</main>
<script>
const EventBus = new Vue({})
Vue.config.devtools = true
const routes = [
{
name: 'home',
path: '/home',
component: ownerhome
},
{
name: 'services',
path: '/services',
component: ownerservices
},
]
const router = new VueRouter({
routes
})
router.beforeEach(async (to, from, next) => {
console.log(to, next)
next()
})
const vue = new Vue({router}).$mount("#main-vue");
</script>
</body>
</html>
It has nothing surprising: the only special is to add VueRouter support.
dashboard.vue
<template id="dashboard">
<div >
<app-frame>
<router-view></router-view>
</app-frame>
</div>
</template>
<script>
Vue.component("dashboard", {
template: "#dashboard"
});
</script>
<style>
</style>
app-frame.vue
<template id="app-frame">
<v-app>
<v-content>
<ownernavbar></ownernavbar>
<glossarysidebar></glossarysidebar>
<v-container>
<slot></slot>
</v-container>
</v-content>
</v-app>
</template>
<script>
Vue.component("app-frame", {template: "#app-frame"});
</script>
<style>
</style>
This two files are straightforward.
home.vue
<template id="ownerhome">
<v-content class="bg-info">
<b-card title="test" tag="article" style="max-width: 20rem;">
<b-card-text>
Text
</b-card-text>
<b-button href="#" variant="primary">Go somewhere</b-button>
</b-card>
</v-content>
</template>
<script>
Vue.component("ownerhome", {
template: "#ownerhome"
})
</script>
<style>
</style>
I feel I miss some nuance, but can’t find it. 😦
Issue Analytics
- State:
- Created 3 years ago
- Comments:14 (14 by maintainers)
Top GitHub Comments
Thanks for the answers. They will most probably make my SPA concept needless.
This
optimizeDependencies
option is great and I’ll check it. ThestateFunction
is also a great alternative for my problem. It is almost identical to handling client side state. Almost, because it has some differences: it contains only data, so if I need to make some post process or would like decorate the pure data with some utility functions, it still has to do with each reload. But this I could live with. A few questions about the use of this function: as I saw in the source (I am away and could only browse the source code of Javalin, but can’t try these features) that this function produces Any and this value is serialized to JSON. Could I inject a pure JSON into the state as is? My server side already has it’s JSON serialization (not pure GSON, they build up the JSON by themself), so I would like to use a stateFunction producing JSON. Is it possible?Also, I will try to figure out why the flickering happens, because it is clear now that the window is cleared long before the page is displayed. I have a guess, but has to check it.
just to also add my 2C, you can also change the caching policy for production for views, by setting
you can also do a bit of UX optimization, by isolating your main theme colors and blocks into its own theme.css and loading that as the first file in your
head
tag and having that cached as well.If you want something that is a huge SPA with complex views, you might be better off using Static files and creating a normal npm project based on Vue js and having a
postbuild
script that moves them into an appropriate java resources folder.Though when using
JavalinVue.optimizeDependncies = true
, you can knock down pages to be into single digit kilobytesYou can also hack in an HTML compressor using an
app.after
middleware to knock it down even further, but that takes CPU on the server-side