Retrieve hash fragment from url with Angular2
TypescriptAngular2 RoutingTypescript Problem Overview
Given this url structure (over which I have no control), how can I retrieve the hash fragment using Angular2?
http://your-redirect-uri#access_token=ACCESS-TOKEN
My router does route to the correct component, but everything after oauth
get scrapped and I can't find the hash fragment in request.params or location.path. Doomed??
Router config:
@RouteConfig([
{path: '/welcome', name: 'Welcome', component: WelcomeComponent, useAsDefault: true},
{path: '/landing/oauth', name: 'Landing', component: LandingComponent} // this one
])
Typescript Solutions
Solution 1 - Typescript
For those still looking :
import { ActivatedRoute } from '@angular/router';
export class MyComponent {
constructor(
private route: ActivatedRoute,
) { }
myfunction(){
this.route.fragment.subscribe((fragment: string) => {
console.log("My hash fragment is here => ", fragment)
})
}
}
Solution 2 - Typescript
To expand on the current answers, I wanted to address an easy way to parse the query params in the hash (specifically for a federated response) since the ActivatedRoute
doesn't seem to handle that natively.
this.route.fragment.subscribe(fragment => {
const response = _.fromPairs(Array.from(new URLSearchParams(fragment)));
response.access_token;
response.id_token;
response.expires_in;
response.token_type;
});
First create a new URLSearchParams object with the fragment to query for its values:
new URLSearchParams(fragment).get('access_token');
For most cases this is probably all that is needed, but if converting this to an object is desired, Array.from
converts URLSearchParams
into an array of arrays that looks like: [['key', 'value'], ...]
. Then lodash's _.fromPairs
converts this to an object.
Solution 3 - Typescript
you can also use ActivatedRouteSnapshot with no need to subscribe for all changes on it.
@Component({templateUrl:'./my-component.html'})
class MyComponent {
constructor(route: ActivatedRoute) {
const fragment: string = route.snapshot.fragment;
}
}
Solution 4 - Typescript
I've taken the comment from nwayve and implemented it using RxJS pipes like this:
this.route.fragment
.pipe(
map(fragment => new URLSearchParams(fragment)),
map(params => ({
access_token: params.get('access_token'),
id_token: params.get('id_token'),
error: params.get('error'),
}))
)
.subscribe(res => console.log('', res));
Solution 5 - Typescript
Assuming you're using ActivatedRoute class in your constructor, try this:
let params = this.route.snapshot.fragment;
const data = JSON.parse(
'{"' +
decodeURI(params)
.replace(/"/g, '\\"')
.replace(/&/g, '","')
.replace(/=/g, '":"') +
'"}'
);
console.log(data); // { json: "with your properties"}
Solution 6 - Typescript
I had the same problem by requesting OAuth server with response_type
=token
, and who redirects to %REDIRECT_URI%#access_token=:access_token&token_type=:token_type&expires_in=:expires_in
.
The problem is, by default, the direct access to sub-url is not routed: in your case, %BASE_URL%/landing/oauth
will not be redirect to LandingComponent
component.
I fixed it with this configuration:
import { bootstrap } from '@angular/platform-browser-dynamic';
import { provide } from '@angular/core';
import { APP_BASE_HREF } from '@angular/common';
import { ROUTER_PROVIDERS } from '@angular/router';
import { AppComponent } from './components/app/app.component';
bootstrap(AppComponent, [
ROUTER_PROVIDERS,
provide(APP_BASE_HREF, { useValue: '/' }) // this line
]);
Solution 7 - Typescript
An option for parsing the fragment data with plain javascript is
this.activatedRoute.fragment.subscribe(value => {
let fragments = value.split('&')
let fragment = {}
fragments.forEach(x => {
let y = x.split('=')
fragment[y[0]] = y[1]
})
})
The information will be in the form of an object which can be easily accessed.
Solution 8 - Typescript
I tried this, but the snapshot was an empty string. https://stackoverflow.com/a/51286916/569302
Here's what worked for me:
ngOnInit(): void {
this.route.fragment.subscribe({
next: value => {
if (value === null) {
throw new Error('not implemented');
}
const access_token = new URLSearchParams(value).get('access_token')
console.log({access_token})
}
});
}
Solution 9 - Typescript
You can retrieve the url fragment at any time using the following code - which makes use of the Router
service:
const urlTree = this.router.parseUrl(this.router.url);
console.log(urlTree.fragment); //access_token=ACCESS-TOKEN