Updated 2022-05-22 2
Viewed 8 times

TL;DR: How can I tell when the ActivatedRoute has finished parsing the QueryParams, even if there are none?

In my Angular 13 application, I have a need to obtain an optional query parameter before I initialise a service which communicates with the server.

This logic occurs in the root component (because I cannot be sure which page the visitor will land on), so the component is loaded before the routing is initialised. For this reason, this.route.snapshot.queryParamMap is empty in both the ngOnInit and ngAfterViewInit events.

I know that I can subscribe to the observable returned by this.route.queryParamMap.subscribe, and this works fine when there are query parameters in the url, however this does not fire if there are no QueryParams available - and due to this, I don't know for sure when the parsing is complete and therefore when to commence connection to the server.

I have tried setting initialNavigation to enabledBlocking but this doesn't seem to help, the queryParams are still not available until some time after the ngAfterViewInit event is called.

My fallback solution is to parse the query string myself, but I don't want to pull in another url parsing library when Angular has a compliant parser built in.

🔴 No definitive solution yet
📌 Solution 1

I listened to all router events and used it to find some params. If optional param jwt is present we can run the service.

  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
export class AppComponent {
  constructor(private router: Router) {
    this.router.events.subscribe((event) => {

      const urlParts = event?.url?.split('?');

      const jwtValue = urlParts?.find((part) => part.includes('jwt'));

      if (jwtValue) {
        console.warn('Run service, jwt is:', jwtValue);
        // go to service


  navigate() {
    this.router.navigate(['authenticate'], { queryParams: { jwt: '123' } });

Here is an example: https://stackblitz.com/edit/angular-navigate-with-query-params-atevru?file=src%2Fapp%2Fapp.component.ts

📌 Solution 2

The working solution was to listen for the ActivationEnd router event, which fires after the router has finished initializing.

Thanks to @Joosep Parts for tipping me off about Router.events

private initialized = false;

public constructor(private readonly router: Router, private readonly route: ActivatedRoute)
    this.router.events.subscribe((data) =>
        if (!this.initialized && data instanceof ActivationEnd)
            this.initialized = true;
            console.log('Initial query param keys: ' + JSON.stringify(route.snapshot.queryParamMap.keys, null, 4));