angular icon indicating copy to clipboard operation
angular copied to clipboard

feat(router): allow guards and resolvers to be plain functions

Open atscott opened this issue 1 year ago • 1 comments

The current Router APIs require guards/resolvers to be present in the DI tree. This is because we want to treat all guards/resolvers equally and some may require dependencies. This requirement results in quite a lot of boilerplate for guards. Here are two examples:

const MY_GUARD = new InjectionToken<any>('my_guard');
…
providers: {provide: MY_GUARD, useValue: () => window.someGlobalState}
…
const route = {path: 'somePath', canActivate: [MY_GUARD]}
@Injectable({providedIn: 'root'})
export class MyGuardWithDependency {
  constructor(private myDep: MyDependency) {}

  canActivate() {
    return myDep.canActivate();
  }
}
…
const route = {path: 'somePath', canActivate: [MyGuardWithDependency]}

Notice that even when we want to write a simple guard that has no dependencies as in the first example, we still have to write either an InjectionToken or an Injectable class.

With this commit router guards and resolvers can be plain old functions. For example:

const route = {path: 'somePath', component: EditCmp, canDeactivate: [(component: EditCmp) => !component.hasUnsavedChanges]}

Additionally, these functions can still use Angular DI with inject from @angular/core.

const route = {path: 'somePath', canActivate: [() => inject(MyDependency).canActivate()]}

Reviewer notes:

  • We should deprecate the Token and class-based guards/resolvers in a follow up. Doing so here would make landing the feature change more difficult.
  • With the above, documentation updates were kept minimal. I have updated the API docs on the Route to indicate pure functions can be used instead of the previous token documentation (which is by far less common and cumbersome). Additionally, the Tour of Heroes only uses the class-based Injectable guards. These examples have also been kept unchanged since we haven't that deprecation will come later. Until then, the most common use-case is what's documented in the Tour of Heroes.
  • A migration can be written along with or as a follow up to the deprecation.
  • The size increased, but actually is actually pretty small considering the scope of the feature. In the long run, this will go back down when we no longer need to handle the deprecated/removed ways of doing guards/resolvers.

atscott avatar Jul 02 '22 00:07 atscott

TGP

atscott avatar Aug 02 '22 20:08 atscott

This PR was merged into the repository by commit 0abb67af59a92a2b29082a259aa9f4ea3fbaab7d.

atscott avatar Aug 05 '22 17:08 atscott

This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.