[Fixed] Angular | Inject service into decorator

Issue

I am trying to inject a service into a decorator function in which I am creating, this is so I can get the contents that are stored inside of variables.

I currently have a basic decorator setup.

export function canEdit(editName: string, service: Service) {
      return function (constructor: any) {
          console.log(constructor);
      }
}

Where I am using this it is asking me for the second parameter, which obviously needs to be dependency injected.

I have also tried the @Inject(Service) which isn’t allowed within functions.

Is there a way that I can do this?

Or is it possible to get the parent classes variables within the decorator?

Solution

Decorators are a TypeScript feature that work outside of Angular’s dependency injection system.

The only solution that I know of is to create a special service that will expose dependencies to the decorator.

@Injectable()
export class DecoratorService {
     private static service: Service | undefined = undefined;
     public constructor(service: Service) {
         DecoratorService.service = service;
     }
     public static getService(): Service {
         if(!DecoratorService.service) {
             throw new Error('DecoratorService not initialized');
         }
         return DecoratorService.service;
     }
}

You can now access the injected service via the above class.

export function canEdit(editName: string) {
      return function (constructor: any) {
          const service = DecoratorService.getService();
          // ^^^ access dependency here
          console.log(constructor);
      }
}

The above will not work unless something in the Angular application depends upon DecoratorService because Angular creates instances when they are needed. So you can inject it into a module to force it to be initialized.

@NgModule({
    provides: [
        DecoratorService
    ]
})
export class MainModule {
    public constructor(service: DecoratorService) {
                      // ^^^ forces an instance to be created
    }
}

Leave a Reply

(*) Required, Your email will not be published