I was trying to change a route parameter with Vue router.
My route is the following :
/document/:id?/:lang?/edit
Id and lang (language) are the parameters.
I want to change the parameter lang using JavaScript without altering the rest of the route. I tried applying the following solution (found here). The solution was made for Vue 2 and not 3. So I tried to make an updated version.
This is my code :
let params = this.$route.params
params.lang = 'en'
this.$router.push({params:params})
When I execute my code, there is no change in the route parameters nor an error logged in the console. Does anyone know a solution to this problem in Vue 3.
Thanks in advance.
It's a bad way to change your route parameter like this.
Instead, replace your route with the same name, same id, but different lang:
this.$router.replace({
name: this.$route.name,
params: {
id: this.$route.params.id,
lang: 'en' // or whatever you want
}
})
Don't forget to watch for the route changes if needed:
watch: {
$route(to, from) {
// if anything needs to be done when the route changes
}
}
Related
I am trying to create a route that can handle both dynamic segments and accept router-props (params). Something like this:
{ path: '/peer:body?', name: 'peer', component: () => import('pages/peer.vue'), props: true }
And eventually push a route like this:
this.$router.push({ path: '/peer/' + row.body, name: 'peer', params: { row: row } })
Unluckily, I am only able to use dynamic segments using pathas route property or params using nameas route property, but never simultaneously.
First, as you already mentioned, when constructing "location descriptor object" for $router.push (or to prop of <router-link>), you can use path or name, not both at the same time (doesn't make sense to do so)
Second, you can pass params only when you use name (as described here - paragraph between first two code samples). To overcome this you can use query instead of params or build whole path including the params into the URL string.
And that brings me to the most important part of my answer. It seems as you are trying to pass a complex object as a route param (and into the target component props). While this is technically possible, it's not a good way of doing things. You have no place in your path definition where to put content of such parameter - it will work with push or clicking <router-link> where parameter is provided as an object, but when user accesses that URL directly (by copying and pasting URL for example), the page will be broken because prop parameter will be missing (as it cannot be extracted directly from the URL).
So my advise is to avoid that. Put your data into something like Vuex and instead of passing whole object by router, pass only some kind of identifier that can be included in the URL, extracted by Router and passed as a prop into target component. Then your target component should grab the Id and use it to query Vuex to get the data it needs...
Example
http://localhost:4200/login?aUasas129198
resolves to
http://localhost:4200/login
What should I do if I want the value after '?'
I tried doing
{ path: 'login/:id', component: LoginComponent },
But it did not work
I also tried
console.log(this.route.snapshot.queryParams);
console.log(this.route.snapshot.params);
But they both return empty object. What should I do now please help
If it’s unavoidable that Angular redirects you immediately and loses the query parameters, you could subscribe to router events and on each NavigationStart for login route get a hold of route’s queryParamMap or snapshot.paramMap before they’re lost in redirection, then you can e.g. pass it to a service and do whatever you wanted to do with it.
Or, as another alternative, you could look into configuring your router with queryParamsHandling: 'preserve', in which case it should pass the query params to the next route (see the section in Angular docs linked below for more on this).
I worked with a project that made use of query params in Angular 5, IIRC I don’t think it would redirect on its own so I’d recommend to look elsewhere in your project but I may be wrong.
See also
Routing & Navigation → Query parameters and fragments in Angular docs
Angular Route Start and Route End Events on StackOverflow
Actually, You are not passing the value in any key:
http://localhost:4200/login?aUasas129198
The proper way should be:
http://localhost:4200/login?anykey=aUasas129198
// get it as
// this._ActivatedRoute.queryParams.subscribe()
If you are using the URI as you shown in your question as:
{ path: 'login/:id', component: LoginComponent }
Then you should pass the value to id as:
http://localhost:4200/login/aUasas129198
// remember the '/' after the login that you didn't use.
// get it as
// this._ActivatedRoute.snapshot.params.id
I would like to provide a path that redirects to a given page based on query parameters. For example:
/redirect?page=hero&id=1
should redirect to:
/hero/1
Is there any way to do this in the route config? Something like:
{ path: 'redirect?page&id', redirectTo: ':page/:id' }
I can get the redirectTo to respect path parameters but not query parameters. Any ideas?
You can try to use redirectTo: '/:page/:id' and provide extracted from your URL page and id values using custom UrlMatcher():
...
const appRoutes: Routes = [
{
path: 'hero/:id',
component: TestComponent
},
{
matcher: redirectMatcher,
redirectTo: '/:page/:id'
}
];
...
/**
* custom url matcher for router config
*/
export function redirectMatcher(url: UrlSegment[]) {
if (url[0] && url[0].path.includes('redirect')) {
const path = url[0].path;
// sanity check
if (path.includes('page') && path.includes('id')) {
return {
consumed: url,
posParams: {
page: new UrlSegment(path.match(/page=([^&]*)/)[1], {}),
id: new UrlSegment(path.match(/id=([^&]*)/)[1], {})
}
}
}
}
return null;
}
STACKBLITZ: https://stackblitz.com/edit/angular-t3tsak?file=app%2Ftest.component.ts
There is another issue when using redirectTo: ..., active link is not updated, actually isActive flag is not set to true, it is seen on my stackblitz when acrive redirection links are not colored in red
No, there is no way of doing it by a configuration. YOu see, Angular's router does not explicitly define query parameters - any url can have an arbitrary number of query params, and the paths '/page/id' and '/page/id?key=value' are treated as the same in Angular and do map to the same component. There are other, more cumbersome workarounds. One is to create a dummy component and redirect based on ActivatedRoute.queryParams Observable from the component's ngOnInit method. You can easily see why this is a bad idea.
Another way is to create a resolver, this way you maybe can dismiss the component declaration and just redirect from the resolver, again, based on the ActivatedRoute.queryParams Observable, which seems cleaner.
But I do not really get why one would need such a route in a front end application, if you want someone to visit '/page/id', then just navigate them to the page, without any intermediary tricks.
I'm using ui-router with Angular 1.6. The root state is the site language (/en, /nl, /de).
Most child states are the same for all languages. However, for some states the names of the child states are translated:
/en/english-state/common-state
/nl/dutch-state/common-state
/de/german-state/common-state
How can I make sure the middle state always matches the lang parameter (en/nl/de) in the parent state? I'd like to use ui-sref without providing the middle state; this should be filled automatically based on the language. When the middle state doesn't match the language in the parent state it should be changed automatically to match the language in the parent state.
I can't find an intuitive solution in the ui-router docs, but perhaps I'm missing something. Anyone done this before?
After a while, I've decided to solve it like this, which I think is the cleanest way to do it:
(Note: This is a simplified version. I've replaced functions with strings , omitted dependencies and removed lines, this is not-working code, it's about the idea).
Expose the language variable in the resolve part of the root state, something like this:
$stateProvider.state({
url: '/{lang:(?:en|nl|de)}',
name: 'root',
[ ... ]
resolve: {
language: function() { return $stateParams.lang }
}
In the child state, check if the URL matches the language:
$stateProvider.state({
url: '/{mySlug:(?:english-state|dutch-state|german-state|__my-state__)}',
name: 'root.child',
resolve: {
checkSlug: function () {
$timout(function() {
if (notMatchesLanguage($stateParams.mySlug, language)) {
var params = JSON.parse(JSON.stringify($stateParams));
params.mySlug = correctSlug;
$state.transitionTo($state.current.name, params, { notify: false });
}
}
}
}
Note the added slug in the mySlug list, __my-state_ _
Now in every ui-sref, or $state.go we can use __my-state_ as mySlug parameter. This strange slug won't match any language and will be replaced with the matching state slug.
In angular 2, is it possible to get the query params in the root component in an "angular way"?
I have a simple plnkr with a root component and two routes/states.
I try to get the parameters with :
export class App implements OnInit {
constructor(private route: ActivatedRoute) {
}
ngOnInit(){
console.log(this.route.snapshot.queryParams);
}
}
If I open the example with a query parameter : plnkr the object in the console log is empty.
But when I click the "One" or "Two" links, it can get the query parameters.
I suppose the root can't see the query parameters because it's not an activated route.
Would the solution be to create a fake root route? Or is there another way to read the url (not talking about native JS).
My use case : Regardless of the route I'm on, I need to be able to check if there is a "token" in the url, read from it and then remove it.
Have a look at my change:
https://plnkr.co/edit/b45VUvfVqUl5u2EuzNI9?p=preview
{
path: '**',
component: App
}
I've added a default route - which should be added to the router. This basically says for any other route passed in then go here.
<a routerLink="**" [queryParams]="{token:12345678}">Home</a>
In the links i added a home link, similar to your other links. When you navigate to one or two, then back to home you will see the token passed in the object.
This is because the token was specified in the link.
This only really works if the link will have the token, either hard coded or dynamically generated by another component.
This might help:
https://angular.io/docs/ts/latest/guide/router.html#!#query-parameters