cli mounted not working the second time via router - vue.js

I created a vue.js router like this:
{
path: '/hello/:type',
name: 'hello',
component: HelloView,
},
in the component "HelloView" i put this mounted:
mounted() {
alert("test")
},
the first time i go to: http://localhost:8080/hello/whatever everything was ok and i get the alert message.
next time i go to other link: http://localhost:8080/hello/whatever2 (via <router-link>) i didn't get the alert message.
how can I make mounted run in the second time?

Related

vue application in php page with router hotlinking

I am currently building a module for a CMS (Joomla) - the frontend of this module is created with VUE 3 incl. Router. The prototype is already working and can be integrated into the CMS Module. Also the router works. If a link is clicked within the VUE app, the corresponding view is displayed. But if the user is now on a subpage of the VUE App and refreshes it (F5 / Ctrl + F5), the page is not found - i think because it exists only in the Vue Router.
To the URL structure:
domain.tld <-- This is where the Vue application is located.
domain.tld/list-:id/item-:id <-- This is the URL for an ITEM
Now I know that it doesn't work like that because the webserver tries to interpret the URL which it can't because parts of it are from VUE.
Is it possible to reconfigure the vue router to work with parameters instead of a "physical" structure?
from: "domain.tld/liste-:id/item-:id"
to: "domain.tld?liste=:id&item=:id"
i think this could solve the issue but i dont know...
Edit:
When i try to use this in the router it still works but has the same effect because yeah "appname" cannot be found by the server..
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/appname?playlist=:id',
name: 'PlaylistDetails',
component: PlaylistDetails,
props: true
},
{
path: '/appname?playlist=:id&video=:vid',
name: 'Player',
component: Player,
props:true
},
]
You can assign a controller to a wild-card, which always return you Vue app:
$router->addMap('/domain.tld/*', 'VueController');
Another approach would be using a # in your URL. Everything after your # will be ignored by the server.
Based on the information i've got from Roman i have changed the routes and added a 404 to the router which refers to home. The views are now been loaded as "url params".
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/#appname?playlist-:id',
name: 'PlaylistDetails',
component: PlaylistDetails,
props: true
},
{
path: '/#appname?playlist-:id&video=:vid',
name: 'Player',
component: Player,
props:true
},
{
// Match all paths vue2 Use * vue3 Use /:pathMatch(.*)* or /:pathMatch(.*) or /:catchAll(.*)
path: "/:pathMatch(.*)*",
name: "404",
component: Home
}
]
If now someone tries to open a site via directlink he got redirected to home.
There might be a better solution but this works when you are using vue inside another PHP app where you are not able to configure the server.
additional info for 404:
https://qdmana.com/2020/12/20201223195804176T.html
It looks that Hotlinks (directly into a view) are not possible in my scenario.

Why does vue route not pass props correctly when reloading or using url?

Route:
{
path: '/markets/:code.:exchange',
name: 'Markets',
component: Markets,
props: true
},
Right now, it works as intended when I do a router push like so:
this.$router.push({name: 'Markets', params: {code: this.model.Code, exchange: this.model.Exchange}})
However, when I enter the url, or reload the page, it shows a blank page and this error:
Uncaught SyntaxError: Unexpected token '<'
For example in the above router push function if I push params: {AAPL, US} it would go to /markets/AAPL.US and correctly pass the props. But if I write the same exact thing in the url and enter, or if I reload the page, nothing shows up, and gives the above error.
whenever you reload a page with props the data in props in lost. Maybe you should consider using state manager like store in your app
https://vuex.vuejs.org/guide/state.html
You have an error in your route, you can't use that dot in the path.. you have to use a slash:
{
path: '/markets/:code/:exchange',
name: 'Markets',
component: Markets,
props: true
},

Accessing $route from Vue.js in SPA

Im trying to accesing meta data from my route in vue.
In routes.js I have for example:
{ path: '/product/:productSlug',
name: 'product.slug',
meta: { layout: "no-snackbar" },
hide: true,
component: require('~/pages/checkout/product'), },
It is no-snackbar I need to access.
Then in App.vue I'm checking to see if this is set:
mounted () {
console.log(this.$root.$route.meta.layout)
}
This console.log outputs undefined. If I console.log this.$root.$route I get the following (the same for this.$route):
fullPath: "/"
hash: ""
matched: []
meta: {empty}
name: null
params: {empty}
path: "/"
query: {}
This is not the right path, name, or ofcause meta data. All is empty. Then when I check in Vue devtools, all settings are correct - also the meta data in $route.
This indicates that the values have yet not been set at the point of logging, since they are "visible" later. If I console.log(this.$root.$route.meta.layout) in a page (not App.vue) in mounted(), all values are also present as they should.
The problem is therefore in App.vue.
What am I missing in order to be able to access $route values in App.vue?
You can use currentRoute via this.$router from any component.
I'm not sure if using mounted() to do this in App.vue will work, but updated() will.
updated() {
console.log(this.$router.currentRoute.meta.layout);
}
Try visiting the route in your browser first for example localhost:3000/product/foo then in your mounted method in App.vue add:
mounted () {
console.log(this.$router.currentRoute.meta.layout)
}
NOTE: You need to be in the route that has the meta property defined in your routes.js or else you will keep getting the undefined error.
To avoid getting the undefined error add the meta property to every route in your routes.js.

How to make stepped navigation using vue router?

I want to make stepped navigation for user signup page
and i wanna make each step a different route but i need to keep url the same for each of it, so that user won't be able to go straight to step 3.
here is what i currently have
routes:
{
path: '/signup',
component: SignupPage,
children: [
{ path: '', name: 'signup.step1', component: SignupStep1 },
{ path: '', name: 'signup.step2', component: SignupStep2 },
{ path: '', name: 'signup.step3', component: SignupStep3 },
{ path: '', name: 'signup.step4', component: SignupStep4 }
]
}
SignupPage:
<header>...</header>
<router-view />
<footer>...</footer>
SignupStep1:
methods: {
nextStep () {
this.$router.push({ name: 'signup.step2' })
}
...
}
but when nextStep method called nothing seems to change
I'll answer this question short.
Two optimal ways to solve this task - use Vuetify and its ready-to-use Steppers-component and the second one - pass data through params from one step to the next one.
Let me explain the second option: vue-router allows us to easily pass any type of data from one url to another without even showing that data somehow to the end user. How to pass data between urls you can read in vue-router docs and in your case you don't even need 4-5-6 components, it will be enough to use 1 component + tab bars or any other element for switching steps.
but when nextStep method called nothing seems to change
That happens because you have 4 paths with the same value - an empty value. vue-router searches routes from top to bottom and if it finds one that matches current path no other records would be checked, thats why you see only singup-page.

How to Properly Use Vue Router beforeRouteEnter or Watch to trigger method in Single File Component?

I'm working on an app in Vue.js using Single File Components and Vue Router. I have a Search component where I need to execute a method to re-populate search results each time a user visits the route. The method executes correctly the first time the route is visited because of the "create" hook:
created: function() {
this.initializeSearch();
},
However, when the user leaves the route (to register or log into the app for instance), and returns to the Search page, I can't seem to find a way to automatically trigger this.initializeSearch() on subsequent visits.
Routes are set up in index.js like so:
import Search from './components/Search.vue';
import Login from './components/Login.vue';
import Register from './components/Register.vue';
// Vue Router Setup
Vue.use(VueRouter)
const routes = [
{ path: '/', component: Search },
{ path: '/register', component: Register },
{ path: '/login', component: Login },
{ path: '*', redirect: '/' }
]
export const router = new VueRouter({
routes
})
I gather that I should be using "watch" or "beforeRouteEnter" but I can't seem to get either to work.
I tried using "watch" like so within my Search component:
watch: {
// Call the method again if the route changes
'$route': 'initializeSearch'
}
And I can't seem to find any documentation explaining how to properly use the beforeRouteEnter callback with a single file component (the vue-router documentation isn't very clear).
Any help on this would be much appreciated.
Since you want to re-populate search results each time a user visits the route.
You can use beforeRouteEnter() in your component as below:
beforeRouteEnter (to, from, next) {
next(vm => {
// access to component's instance using `vm` .
// this is done because this navigation guard is called before the component is created.
// clear your previously populated search results.
// re-populate search results
vm.initializeSearch();
})
}
You can read more about navigation guards here
Here is the working fiddle