DATEV Nine-Nine | Standalone Part 2

DATEV eG
DATEV TechBlog
Published in
3 min readJul 25, 2023

By: Matthias Alt, Stephan Bierwirth & Gerrit Riesch, with Tom Auer

© alexbrylovhk / fotolia.com (ID:11504)

Intro

Standalone components are now stable and all that class boilerplate for router guards and interceptors is a thing of the past? It’s been a while since our Halloween special on standalone components and already several things have changed with new features having arrived in Angular. In fact, with all the possibilities that stable standalone APIs provide, we now even have functional router guards and functional interceptors in Angular 15. This means that you can write guards and interceptors as functions. Angular claims less boilerplate and direct dependency injection with the inject function. So, what the heck are we waiting for? Let’s do this!

Functional Guards

With functional router guards we get rid of the classic Guard implementation, can use anonymous functions or inject a Service and call a provided function and have less Boilerplate code. To show you the differences, the following gists represent the same logic for the old and new way.

Common AuthGuard Implementation (deprecated) and Usage:

Old App Module with AuthGuard (github.com)

New AuthGuard Implementation (Angular 15+) and Usage:

In conclusion we need fewer components to provide our application with an AuthGuard. We would recommend using service injection and usage of a public function because we can test this function detached from dependent logic with Unit Tests and do not have to test it implicitly with e.q. E2E or component integration tests.

Setup

To follow our tutorial, you need an Angular 15+ App. If you do not have one, you can create one by:

npx @angular/cli@latest new PoliceGuardApp –directory ./

(Or you upgrade your existing App via the Angular Update Guide.)

You can use a standalone-only App, or you can combine it with the classic AppModule way.

Functional Interceptors

Since Angular 15 we no longer need to write our Interceptors as a Class with the @Injectable Annotation. Instead we can use the built-in withInterceptors() Function which makes it possible to add 1-n functional-style HTTP interceptors to the configuration of the HttpClient instance.

There is also a way to mix the old and the new way via the withInterceptorsFromDi() function but you should prefer the withInterceptors and aforementioned functional interceptors instead. After all, if canActivate and all the other router guard interfaces are deprecated, who is to say DI-provided interceptors won’t suffer the same fate in the future?

The Functional Interceptor takes the request which you can manipulate in whatever way or form fits your business logic etc. and a function for handling the request.

Common implementation of interceptors

Interceptor

Module

Additional opportunity for Interceptors in Angular 15

Tip: In your standalone component you can go as far as to only use a single directive import for e.g., ngIf by importing the NgIf Directive in the Imports Array of the standalone component.

Final thoughts

Finally, the days are gone where Interceptors and Guards must be defined as classes in their own TS-Files. With Standalone-Interceptors/-Guards it is possible to define them where they are used instead. This will not only reduce the number of files we have to maintain and test but also brings their implemented logic closer to the parts of the system where they are used.

We hope you enjoyed our blog, and we would love to see you next time!

Your three DATEV Nine-Nine detectives,

Matthias Alt (LinkedIn)

Stephan Bierwirth (LinkedIn)

Gerrit Riesch (LinkedIn)

--

--

DATEV eG
DATEV TechBlog

DATEV eG steht für qualitativ hochwertige Softwarelösungen und IT-Dienstleistungen für Steuerberater, Wirtschaftsprüfer, Rechtsanwälte und Unternehmen.