Search code examples
angularangular-routerangular-changedetectionvirtual-dom

Component outside of router-outlet, does not have its window.location.href updated after router redirect via guard?


I have this navigation component which sits outside of the router, it makes use of a reusable icon component which relies on the absolute url to point to SVG icons, which is retrieved via getter within the component:

public get absUrl(): string {
    return window.location.href.split('#')[0];
  }

Unfortunately upon redirect the view isn't updated with the new abs url, when triggered from guard.

I've made a workaround with setTimeout but its super hacky -- its purely to demonstrate that there's some delay in the chain that's causing the issue as eventually, the value for window.location.href is correct.

Here's the workaround:

public absUrl = window.location.href.split('#')[0];

  ngAfterViewInit() {
    setTimeout(() => {
      this.absUrl = window.location.href.split('#')[0];
      this.ref.detectChanges();
    }, 200);
  }
  • Only when loading the whole app at a protected route, trying to subsequentially access protected route after loading the app will work fine.
  • This occurs when loading the whole app at a non-existant route and being redirected to /404
  • If I set 0 - 100ms timeout, it will not update in time
  • The component loaded via router-outlet works, the abs url within the icons are updated accurately.

Does anyone have any ideas on how to properly implement this one? My hunch is it has something to do with how the app is loaded the very first time if you're trying to load a protected route.


Solution

  • I suppose you can do something like this using the Location service:

    public absUrl = window.location.href.split('#')[0];
    
    constructor(location: Location, ref: ChangeDetectorRef) {
      location.onUrlChange((s) => {
        this.absUrl = window.location.href.split('#')[0]);
        ref.detectChanges();
      });
    }