Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 4 Custom decorator - injecting services

I want to create an authentication decorator in my application.

Usage example should be simple as

@RequireAuthentication()
@HostListener('click', ['$event']) onClick(event: Event) {
  // ...
}

As I know decorator can only be function, so in some other file I plan to have

export function RequireAuthentication() {
    if (!userService.isAuthenticated) {
        navigationService.goToLogin();
        return;
    }
}

The problem for me is how to properly initialize userService and navigationService in this case, since these services contain all logic for finding if a user is authenticated and showing login screen.

I already tried:

  1. to use a class with the constructor for service initialization, but then the nested method cannot be used as a decorator
  2. to use Injectable class to create services, I need to create an instance of this class, same problem.
  3. to use ModuleWithProviders approach to hide authentication implementation and only expose decorator, but not sure if that is the right way to do this.

Any hints would be helpful. Could be that I miss something fundamental since I'm not an experienced angular developer or there is another way to approach this problem.

like image 902
Minja Avatar asked Feb 20 '18 14:02

Minja


1 Answers

As explained in this answer, the solution that is idiomatic to the framework is to expose injector class instance property, so it could be accessed inside decorator. The existence of injector property can be also secured with an interface.

Since property decorator runs once and has access to class prototype but not instance, it's necessary to patch ngOnOnit method and retrieve all necessary services inside patched method with this.injector.get().

The alternative is to expose global injector to some object, as explained here. This is not idiomatic solution but a hack that will result in certain limitations and negative consequences. It can hardly be recommended for use in production.

like image 194
Estus Flask Avatar answered Nov 11 '22 11:11

Estus Flask