Retrieve hash fragment from url with Angular2

TypescriptAngular2 Routing

Typescript 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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMFBView Question on Stackoverflow
Solution 1 - TypescriptIsmail HView Answer on Stackoverflow
Solution 2 - TypescriptnwayveView Answer on Stackoverflow
Solution 3 - TypescriptAya AzzamView Answer on Stackoverflow
Solution 4 - TypescriptbeemanView Answer on Stackoverflow
Solution 5 - TypescriptTecayehuatlView Answer on Stackoverflow
Solution 6 - TypescriptPinguet62View Answer on Stackoverflow
Solution 7 - TypescriptSameer BasilView Answer on Stackoverflow
Solution 8 - TypescriptJesus is LordView Answer on Stackoverflow
Solution 9 - TypescriptDrenaiView Answer on Stackoverflow