Home > Software engineering >  Angular Router - redirect to route with fragment without adding to history
Angular Router - redirect to route with fragment without adding to history

Time:10-31

I have this route in my routing module:

{ path: 'signup', component: SignupComponent },

But this route shouldn't be accessed without fragments (#first-step, #second-step), so I've added some redirect logic into my app:

this.route.fragment.subscribe((fragment: string | null) => {
  if (fragment && ['first-step', 'second-step'].includes(fragment)) {
    // Fragments are correct, further logic with displaying step components
  } else {
    this.router.navigate(['signup'], {fragment: 'first-step', replaceUrl: true});
  }
})

I use navigate because fragments are client part of the url and it can be changed only on client, but there is a problem with browser history, with this approach it pushes poth pages - signup and signup#first-step. skipLocationChange will not help here as it doesn't change url. I can simply define fragment in registration button on main page but what if user will open signup page directly from the bookmarks or address bar? I would like to have nice redirect without adding signup page to the history, how can it be done? Is there anything I don't understand correctly?

CodePudding user response:

You could move the logic to a Guard, so it gets process before the navigation completes.

@Injectable({ providedIn: 'root' })
export class SignupGuard implements CanActivate {
  constructor(private router: Router) {}

  canActivate(route: ActivatedRouteSnapshot): boolean | UrlTree {
    const {fragment} = route;
    
    // has required fragment proceed with navigation
    if (fragment && ['first-step', 'second-step'].includes(fragment)){
      return true;
    }
    
    //no fragment present, return UrlTree to 'signup#first-step' for redirection
    return this.router.createUrlTree(['signup'], { fragment: 'first-step' });
  }
}

And then use the guard in the Route:

{
  path: 'signup',
  component: SignupComponent,
  canActivate: [SignupGuard],
  runGuardsAndResolvers: 'always',
},

I added the runGuardsAndResolvers so the guard also gets processed while trying to navigate to signup when on signup#first-step or signup#second-step. You can remove it if that's not possible within your app.

Cheers

  • Related