Change 'components only' in navigation guard - vuejs2

I want to see if I can exchange my components (one in 'default' router-view and another in 'navDrawer' router-view) before the launch of the page. 'Exchanging' would just be derogative goal to what I actually want to achieve.
Eventually, I would want to pass an argument into the component before loading the whole page itself but apparently the component is loaded through this router and I want to pre-check(with or without guard) before I decide what props to pass into the components.
Here is my routers/index.js
Landing & LandingButtonBar are components.
1 export default new Router({
2 routes: [
3 {
4 path: '/',
5 name: 'Landing',
6 components: {
7 default: Landing,
8 navDrawer: LandingButtonBar
9 },
10 // Guard
11 beforeEnter: (to, from, next) => {
// put some conditions here to invoke the next line.
12 next({
13 // path: '/', // this will obviously cause a recursion
14 components: {
15 default: LandingButtonBar,
16 navDrawer: Landing
}
})
}
}
]
})
Everything works as expected. But I also hoped that the components would exchange each other before loading. Is this possible using within routes?
Attempt 1:
Self directing the guard would work for like 0.01 sec but then it would get caught up in an infinite loop. i.e. uncommenting line no 13. Also removing the 'path' attribute would have no effect after loading the page. Failed.

Related

Handling thousands of custom routes from a database in Nuxt.js

I have a Nuxt JS (v3) application with thousands of custom routes, many pointing to the same pages, but at the domain root.
e.g /some-product-name-one, /a-secondary-product-name, /some-category-name, /some-static-page.
So in this case, the slug can be anything at domain root level, which is why i must fetch it from my database to assert which component is to be used.
What i've done is fetch all the routes (about 27.000) from my Database via. an API on build in my app/router.options.ts so it looks like so:
import type { RouterOptions } from '#nuxt/schema'
export default <RouterOptions> {
routes: (_routes) => [
{
name: 'product_some-product-name-one',
path: '/some-product-name-one',
component: () => import('~/pages/product.vue'),
props: {
id: '2421'
}
},
{
name: 'category_some-category-name',
path: '/some-category-name',
component: () => import('~/pages/category.vue'),
props: {
id: '45'
}
},
{...}
]
}
Now, the build time was 10 minutes and the application is extremely slow. Navigating to the website timed out.
How can i fetch routes from my database in Nuxt.js and send the user to the correct component?
Rather than baking all of the routes individually into the router, you might want to use a dynamic route such as _id.vue and handle the varying parameter within the component.

How to implement permalinks in a serverless Vue SPA

I made this little app which is a simple Vue serverless SPA. I wish to pass an array of strings and a an array of numbers through the URL so that I can share "states" of the websites with colleagues. I understand vue-routercan update the route's parameters as per their documentation, but I do not have enough perspective to see how to implement this to solve my problem. I would love some help or guidance so I actually learn from this. Thank you all.
EDIT: after Mr. Luis Brito's hint.
I added the following to my code (props)
const router = new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'home',
component: require('#/views/Home').default,
props: { myNumbers: [1,2,3]}
},
]
})
in a component I did
mounted () {
this.$router.push({ name: 'myNumbers', params: {myNumbers: [1,2,3,4] }})
const myNumbers = this.$route.params.myNumbers
console.log(myNumbers);
}
But now my App throws a Vue-Router error [vue-router] Route with name 'myNumbers' does not exist but it does console log the numbers I pushed. Is it possible to make my app look for props and only if they are there to do something with them? Otherwise I get a white screen.
The way I see to solve this problem is use vue-router with a route that passes props to the component, that prop can be an object containing the two arrays that you mentioned.
Referer to Vue Router - Obect Mode
Here is an example for the router:
const routes = {
path: '/promotion/from-newsletter',
component: Promotion,
props: { myNumbers: [1,2,3,5,8], myStrings: ['first', 'second', 'third']
}
}
On the component side, you can access those props on created() lifecycle hook, or mounted()
props: ['myNumbers','myStrings '],
mounted() {
if ( this.myNumbers !== undefined && this.myStrings !== undefined ) {
console.log(thys.myNumbers, this.myStrings);
}
}
So that http://localhost:8080/?myStrings=layer1,layer2,layer3&myNumbers=-1,2,3-4 would console log layer 1-3 and the numbers.
EDITED
TO pass the values programatically, would be better to use Function Mode to capture the URL params and pass it to component. Another way would be to create a component where you can input the numbers and strings that you want, and then call the router and pass those values to the route for the final destination component.

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 redirect non-dynamic urls with vue-router

We have a vue.js app for an insurance company where every agent has their own dynamically-generated website. Currently, if you visit a gibberish link, it will show the blank agent template. We need urls that don't include an agent's slug to redirect to our "NotFound" component.
Below is our vue-router code if there happens to be an easy fix. Otherwise is it easier to add a computed function to redirect a visitor if, for example, the agent.name == null?
Thanks for any help!
Example of a good url: https://my.piaselect.com/georgebeach
Example of a bad url: https://my.piaselect.com/georgebeach2
Our router:
{
path: "/:id",
component: AgentSite,
name: 'AgentSite',
props: true
},
{
path: '*',
name: 'NotFound',
component: NotFound
}
Building on what #Jacob Goh has said.
You need a way to to now if the agent id is valid or not. Let's assume you have a list of agent id's, you can use a route guard to block the route to invalid ids.
https://router.vuejs.org/en/advanced/navigation-guards.html
I haven't tested this, but you should be able to get the general idea.
const agentIds = ['Bob', 'Michael']
const router = new VueRouter({
routes: [
{
path: '/foo:id',
component: Foo,
beforeEnter: (to, from, next) => {
if (agentIds.includes(to.params.id)) {
// The agent is fine - continue
next();
} else {
// doesn't exist - go back to root or any other page
next({ path: '/' });
}
}
}
]
})
it doesn't work because you don't specify any name in this path :
{
path: "/:id",
component: AgentSite,
name: 'AgentSite',
props: true
},
because of that, this path allow any random chars at the root to return the component AgentSite (but blank because the random chars "param" fit to nothing in the component i guess).
To prevent that, you can specify a name to your path : path: "agent/:id" for example.
Edit : it seems you already had a great solution here...

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