How to get query params in root component? - javascript

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

Related

Vue $route.push not working when called from method

I'm building a search bar for my app with vue-bootstrap-typeahead autocomplete lib, if your not familiar with it, when you click a suggested result it triggers the #hit event, passing the result data to the method.
<vue-bootstrap-typeahead
...
#hit="goToResult"
...
/>
Then I have the goToResult method
methods: {
goToResult(result) {
this.$router.push({name: 'market', params: {marketId: result.id}});
},
...
}
When I do search from a non-market route it works fine, redirecting the user to the desired /market/:marketId route, but when it's done from a "market" route it just changes the URL but doesn't redirects to the new market, it even triggers the "duplicated route" error if I click the same result twice, but still not redirecting.
Any suggestion?
Thanks
Check out the note at the bottom of the router.push section: https://router.vuejs.org/guide/essentials/navigation.html
Note: If the destination is the same as the current route and only params are changing (e.g. going from one profile to another /users/1 -> /users/2), you will have to use beforeRouteUpdate to react to changes (e.g. fetching the user information).
...and here is how to use beforeRouteUpdate:
https://router.vuejs.org/guide/essentials/dynamic-matching.html#reacting-to-params-changes
Hope this helps!

Vue Router dynamic segment with params

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...

Angular 6 removes query string from url

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

Handling Dynamic URL Params via RouterLink in Angular App

In my Angular 2 app I have a tab area where users can select from a group of independent, but contextually related components. When they click on one of these links, the relevant component loads according to what's defined in the routerLink, like this:
<a class="page-content-header-item" routerLink="/page1" routerLinkActive="selected">Page 1</a>
This was working well. However, since then we've built the app to save various user-selected filter selections as params in the URL. This way when they re-load the component, they'll have their most recent selections still visible and applied to the data. So the URL might look like this after the user had made some filter selections:
http://somesite.com/page1;language_filter=true;language_selection=English
The component code for this looks like this:
public changePage(page, value, type, body)
{
this.onUserSelection(value, type, body, page);
this.route.params.subscribe(
(params: any) => {
this.page = params['page'];
this.language_filter = params['language_filter'];
this.language_selection = params['language_selection'];
}
);
this.router.navigate(
['/page1', {
page: page,
language_filter: this.language_filter,
language_selection: this.language_selection,
}]);
}
This works well for the main navigation methods, that are accomplished via a routing file, where each one looks like this:
{ path: 'page1', component: Page1Component, canActivate: [AuthGuard], data: {contentId: 'page1'} }
However, for this tab area I mentioned, it's loading components according to a hard-coded routerLink param. So I realize now that when a user navigates BACK to a component that way, as opposed to via one of the other ways we make available, it actually overrides the URL params - because it's literally loading "page1" -- because of this <a class="page-content-header-item" routerLink="/page1" routerLinkActive="selected">Page 1</a>
... and thus the URL params that had been added previously are wiped out.
So, my question is, is there a way I can edit this code:
<a class="page-content-header-item" routerLink="/page1" routerLinkActive="selected">Page 1</a>
... so it allows for some dynamic variables? Or do I have to find a new way to handle the navigation in this tab area?
Here is the solution I came to using queryParams.
First, you can pass parameters in your routerLink directive using the queryParams directive:
<a routerLink="/page1" [queryParams]="fooParams">Page 1</a>
<a routerLink="/page2">Page 2</a>
<router-outlet></router-outlet>
where fooParams is a plain object:
export class MainComponent {
fooParams = {
language_filter: true,
language_selection: 'english'
}
}
Angular will output this url like
href="localhost:4200/page1?language_filter=true&language_selection=english"
What you have to do next, is set up a way to intercept the ActivatedRoute, so you can extract the values of the params from the ActivatedRouteSnapshot. You can do this either using a resolver or directly in your component. In my example I used a resolver:
#Injectable()
export class RoutingResolve implements Resolve<any> {
resolve(routeSnapshot: ActivatedRouteSnapshot) {
const { language_filter, language_selection } = routeSnapshot.queryParams;
return { language_filter, language_selection };
}
}
And then pass that resolver in the route definition:
const ROUTES: Routes = [
{
path: 'page1',
component: PageOneComponent,
// In this route we define a resolver so we can intercept the
// activatedRoute snapshot before the component is loaded
resolve: {
routing: RoutingResolve
}
},
{
path: 'page2',
component: PageTwoComponent
}
];
Then, inside PageOneComponent you can subscribe to the resolved data and do whatever you want with it, like for example, setting the value of a form with it and updating the queryParams on form change.
For the full example, check out this plunker
Make sure to open the preview in a separate window, so you can see the route changes in your browser.
If you navigate to Page 1, change the values in the form, then navigate to Page 2, and then press back in your browser, you can see the values loaded in the form correspond to the params in the url.

Ember - abort the route and reload the route with same model

In my ember app, when the user clicks the Back button of browser,I need to stop the transition (whereever it might take me as per Ember history) and reload the same url with same model. Have tried the below code, but doesnt seem to work:
search-route.js
var route = Ember.route.extend({
actions:{
willTransition: function(transition){
if(this.controller.get('order') === 1){
transition.abort();
this.transitionTo('search',model)
}
}
}
})
This doesnt seem to work and gives error about query params. So, i looked for what is there in transition object. Saw that as soon as I enter this code, the object transition contains prop queryParams but with the old values, not the current URL one. But there is another prop - transition.intent.preTransitionState.fullQueryParams which contains the current URL query params. Would that be used here somehow.
I looked for solutions and someone also suggested to put in this.refresh(), but also didn't work.
I'm trying on my own ember app and doing a transition.abort() followed with a this.refresh() works.

Categories