Vue.js - Define path of vue route based on URL query params - javascript

Let's assume I have this URL
http://localhost:8080/public/form?code=fhuZ15aHy
I have defined a route in my route.js file like this
{
path: '/public/form?code=:code',
name: 'survey',
component: () => import('./views/form')
}
which is supposed to reuse the same component based on the code query parameter coming from URL.
In my form.vue component I have defined a prop like this:
props: {
code: {
type: String,
required: true
}
}
But this is not working, in the sense that I am not redirected to any page.
I think I'm doing wrong with how I defined the path of the route. How can I achieve this?

Do not define the query within the path
You should write like this:
{
path: '/public/form',
name: 'survey',
component: () => import('./views/form')
}
router.push({ path: '/public/form', query: { code } })
And within the component you can access the query like this
const {code} = this.$route.query

Related

Check if currentRoute starts with some text(something/something/*...) in Angular

I want to stop loader from loading from few screens and therefore I applied ngIf at routes where loader isn't needed. Here is the code for app.component.ts :
<router-outlet>
<app-spinner></app-spinner>
<ngx-ui-loader *ngIf="!(currentRoute =='/dashboard' || currentRoute == '/vehicle/edit/')"></ngx-ui-loader>
</router-outlet>
app.component.html
this.currentRoute = "";
this.router.events.subscribe((event: Event) => {
if (event instanceof NavigationEnd) {
this.currentRoute = event.url;
}
});
I need to add * to vehicle/edit URL as there can be any vehicle ID while fetching the edit page like : /vehicle/edit/49042/1422, /vehicle/edit/49023/1421 and so on.
How to allow currentRoute accept /vehicle/edit/* ?
Ok, so to answer your question about route that accepts dynamic URLS/all URLS starting with /vehicle/edit/.
The "dummy" approach if you know that your nesting got limit, is to declare multiple routes with params, more-less like this:
const routes: Routes = [
{ path: '/vehicle/edit/', component: VehicleListComponent },
{ path: '/vehicle/edit/:id', component: VehicleEditComponent },
{ path: '/vehicle/edit/:parent/:id', component: VehicleEditComponent },
{ path: '/vehicle/edit/:grandparent/:parent/:id', component: VehicleEditComponent },
];
This will work, because Angular routing stops at very first matching path, so the order of your route declaration is important!
However, if you're dealing with very long nesting capability, better approach is to use custom route matcher:
import { UrlSegment } from '#angular/router';
const nestedCategoryMatcher = (url: UrlSegment[]) => {
// Check if this regex actually match your requirements
const regexMatcher = /^(vehicle\/edit)([\/][0-9]+.+)/;
if (!url.join('/').match(regexMatcher)) return null;
return ({ consumed: url });
}
const routes: Routes = [
{ path: '/vehicle/edit/', component: VehicleListComponent },
{ matcher: nestedCategoryMatcher, component: VehicleEditComponent },
];
And remember, that by using matcher, you will have to retrieve your "params" manually in your components by splitting URL into segments.
this.route.url
.subscribe(segments => {
const urlSegment: UrlSegment[] = (segments as UrlSegment[]);
console.log(urlSegment);
});

Why passing data through Vue-router returning "[object Object]"?

What I'm trying to do is to pass some data from one component to another via router (I'm using Vue-Router-4 with Vue 3.0). But the data that I'm getting back is just "[object Object]" instead of the actual value. Here is what I did. Inside the component that sends the data I have this function
goToQuestions() {
this.$router.push({
name: "QuestionsPage",
params: {
data: this.questions
},
});
},
inside my index.js I have this
{
path: "/questions-page",
name: "QuestionsPage",
props: true,
component: () =>
import ('#/views/QuestionsPage.vue')
},
And then inside the receiver component I have this snippet
props: ["data"],
mounted() {
console.log("data coming from the router", this.data);
},
I am assuming you this.questions is either array or object.
with router it is advised not to send objects and arrays. Instead send an id .
And on the receiver page use that id to fetch the data.
Even if you want to pass object you can try this:
when adding routes, use props's Function mode so that it has a default property user and it will add route.params as props.
{
path: '/questions',
name: 'questions',
component: QuestionsComponent,
props: (route) => ({
user: userData,
...route.params
})
}
use this to push into your route
self.$router.push({
name: 'questions',
params: {
data: this.questions
}
})

JavaScript: Evaluating export code directly from string

How does one run and resolve a JavaScript export module directly from a string?
Here's a concrete example: The module vue-route-generator generates export code that returns a Vue Router configuration object. So when I issue this command:
const routes = require('vue-route-generator').generateRoutes(...);
routes is a string containing code, something like this:
function index() {
return import('/home/jay/Documents/industrial/resources/js/sections/index.vue');
}
function people() {
return import('/home/jay/Documents/industrial/resources/js/sections/people.vue');
}
export default [
{ name: 'index', path: '/', component: index },
{ name: 'people', path: '/people', component: people },
];
How do I run this code and get the object without saving this code to a separate file? I'm using Webpack as my builder but a solution that works for other builders would be appreciated.

Angular Routing: Define Multiple Paths for Single Route

I've seen several answers to this, but I'm not sure if they necessarily "fit" my scenario (I'm not trying to create parent/child routing relationships or anything like that). In my case I have a component that's responsible for adding new widgets, or editing existing widgets. My routes are defined like so:
const routes: Routes = [
{
path: 'widget/add',
component: ManageWidgetComponent,
canActivate: [CanActivateViaRoleGuard],
data: { roles: ['Admin', 'User'] }
},
{
path: 'widget/:id/edit',
component: ManageWidgetComponent,
canActivate: [CanActivateViaRoleGuard],
data: { roles: ['Admin', 'User'] }
},
];
path is a string so it can't accept an array of values or anything like that. Is there a way to specify multiple paths for a single route so I don't have to duplicate the other parts of the route (the component, canActivate, and data parts)?
Note: The paths cannot be changed due to application requirements (i.e. I can't just make a single manage path).
Edit: My ManageWidgetComponent already has the correct logic for handling Create vs. Edit. That part's fine.
I think you could do something like this :
const routes: Routes = ['widget/add', 'widget/:id/edit'].map(path => {
return {
path: path,
component: ManageWidgetComponent,
canActivate: [CanActivateViaRoleGuard],
data: { roles: ['Admin', 'User'] }
};
});
you can use this format :
{
path: 'widget/:id/add-edit',
component: ManageWidgetComponent,
canActivate: [CanActivateViaRoleGuard],
data: { roles: ['Admin', 'User'] }
},
and in ManageWidgetComponent use fallowing code to check if there is a value for "id"? if there is no value for id so you are adding a new user and if there is a value for "id" so you are editing a user.
this.route.params.subscribe((params: any) => {
if (params.id) {
//////you are editing a user
}else{
///// you are adding a new user
}
}
);
By convention, there is a one to one relationship between a route and a path (they are basically the same thing), So you can't have different paths for a single routes.
But you can have different paths that loads the same component (and that's what you're doing in the example above)
A way to solve this problem would be :
{
path: 'widget/:id',
component: ManageWidgetComponent,
canActivate: [CanActivateViaRoleGuard],
data: { roles: ['Admin', 'User'] }
},
Then you can navigate to widget/add or widget/123
And in ManageWidgetComponent:
this.route.params.subscribe((params) => {
if (params.id === 'add') {
// Add new user
} else {
// Edit user with id = +params.id
}
});

Vue, is there a way to pass data between routes without URL params?

I am looking how to pass data secretly between two separate components (not parent and child) without using URL params in my Vue2 app. This doesn't mean I am passing secrets but rather I just dont want the user to see it (only for UI considerations).
I know Vue has Props but they are meant for passing data between parent and child component.
In my case, my URL will change but I don't want to pass data via visible params.
Someone claimed to use props without URL params here but I haven't been able to reproduce a working solution (getting undefined each time).
I also checked out these options but they are all using either URL or query params which as we know are visible.
An ugly solution would be to write the data to local storage and then read it there but this creates a lot of overhead and complexity (like what if I only want this data to be read once, etc).
Is there a more elegant solution to this problem?
Thanks!
make props: true for the destination route -- in the index.js file of router
{
path: '/home',
name: 'home',
component: taskChooser,
props: true,
}
define prop in the component e.g props: ['myprop'], - note the quotes
copy the variable you want to pass from the source route into the same name as your prop - in this case myprop
myprop = theVariableThatYouWantToPass
this.$router.replace({name:'home', params:{myprop}});
Make sure that the name of prop and variable are same - the prop is in quotes.
It's working for me.
Thanks #Mayank for pointing me in the correct direction.
Here is the correct syntax that worked for me.
Notice the props in In router index
{
path: '/componentPath',
name: 'componentName',
props: {
header: true,
content: true
},
}
In the component you are redirecting to, define the props as following:
props: {
myProperty: {
type: <DATATYPE>
},
}
Perform redirect as following:
this.$router.push({
name: 'componentName',
params: {
myProperty: <VARIABLE>
}
})
Access props with the this. convention from created or in later lifecycle event.
In this case, the variable name and property name do not have to be the same as it is a simple map. That naming convention would be a curious design choice anyway.
I haven't tested this in Vue 2, but in Vue 3, you can pass a stringified object through the props when you click on a link:
Add props: true to your routes file, for the route.
{
path: 'receipt',
name: 'receipt',
component: () => import('../pages/Receipt.vue'),
props: true,
beforeEnter(to, from, next) {
if (!to.params.receiptData) {
return next({
name: 'dashboard',
params: {
locale: from.params.locale ? from.params.locale : 'en',
},
});
}
return next();
},
},
Include your stringified object as a param for router.push().
const receiptData = {
transferType: 'default',
recipient: receiver.value.name,
referenceNumber: '#B3423424234',
amountSent: formAmount,
transferFee: 0,
};
router.push({
name: 'receipt',
params: {
receiptData: JSON.stringify(receiptData),
},
});
Declare the props as instance data in the component.
<script setup>
import { computed } from 'vue';
const props = defineProps({
receiptData: {
type: String,
required: true,
},
})
console.log('receiptData', props.receiptData);
const parsedReceiptData = computed(() => JSON.parse(props.receiptData));
</script>
I haven't tested an upper limit for size, so be careful about passing a huge object through, and you'll notice I showed a beforeEnter middleware on the route too because, if the user presses F5 to refresh the page, the props will be lost, so in my case, I redirect the user away from the page because the receipt is for one time use only.

Categories

Resources