angulartypescriptroutesangular2-routing

Platform-based redirect in Angular 16


I have a module of my a that contains its own subrouting. Essentially, the only content of this page are a header and some material tabs that are linked to my routing,so I will only be displaying one of them. I would like the landing tab to be different whether I am on desktop or mobile however.

I have a service named ToolService containing the method ToolService.isDesktopOrTablet() which I usually use to do my platform detection.

Before realizing I wanted the redirectTo to point to 'list' instead of 'tree' on mobile, my routing module looked something like

export const routes: Routes = [
  {
    path: '',
    component: ExampleComponent,
    children: [{
      path: '',
      redirectTo: 'tree',
      pathMatch: 'full',
    }, {
      path: 'tree',
      component: ExampleTreeComponent,
      title: 'Example Title',
    }, {
      path: 'list',
      component: ExampleListComponent,
      title: 'Example Title',
    }]
  }
]

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [],
})
export class ExampleRoutingModule {
}

The first thing I tried was using a class-based guard. This is when I learned that in Angular 15 class-based guards were deprecated in favor of functional guards.

The second thing I tried was using a functional guard, but I was greeted with a warning message that told me that canActivate and redirectTo do not play well together as redirects are processed before guards.

Which brings me to the third solution i tried, a resolver:

export const exampleResolver: ResolveFn<string> = (): string => inject(ToolService).isDesktopOrTablet() ? 'tree' : 'list'

export const routes: Routes = [
  {
    path: '',
    component: ExampleComponent,
    children: [{
      path: '',
      redirectTo: '',
      pathMatch: 'full',
      resolve: {
        redirectTo: exampleResolver
      },
    }, {
      path: 'tree',
      component: ExampleTreeComponent,
      title: 'Example Title',
    }, {
      path: 'list',
      component: ExampleListComponent,
      title: 'Example Title',
    }]
  }
]

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [],
  providers: [ToolService]
})
export class ExampleRoutingModule {
}

This doesn't appear to provoke any error message, but it also does not appear to do anything. When I navigate to the main route, my app stays on the '' route without actually redirecting to anything, as if the resolver was never executed, which brings me to my questions:

  1. is my resolver incorrect in some way?
  2. is a resolver the right tool for this job?
  3. if so? what am I doing wrong?
  4. if not, what should I be using instead? Did I give up on guards too early?

Solution

  • I would go with a CanActivateFn guard.

    function canActivate() {
       const router = inject(Router)
       if(isMobile) {
         return router.createUrlTree(['list']);
       } else {
         return true
       }
    }