Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Angular @Injectable with a function (not a class)

I'm creating a service for an Angular (2+) application and all the documentation uses classes, but I prefer to write the service as a function.

Here's what I want to work (but doesn't):

import { Injectable } from '@angular/core';

export const AframeMessengerService = Injectable()(function AframeMessengerService() {
    console.log('aframe messenger');
});

With this, I get this error in the file which injects it:

Cannot find name 'AframeMessengerService'.

Here's what does work, but is not what I want:

import { Injectable } from '@angular/core';

@Injectable()
export class AframeMessengerService {
    constructor() {
        console.log('aframe messenger');
    }
}
like image 877
Kevin Beal Avatar asked Aug 17 '17 17:08

Kevin Beal


People also ask

Is @injectable a class decorator?

Statements that look like @SomeName are decorators. Decorators are a proposed extension to JavaScript. In short, decorators let programmers modify and/or tag methods, classes, properties and parameters. In this section the focus will be on decorators relevant to DI: @Inject and @Injectable .

What is difference between @inject and @injectable in Angular?

We use the @Inject parameter decorator to instruct Angular we want to resolve a token and inject a dependency into a constructor. We use the @Injectable class decorators to automatically resolve and inject all the parameters of class constructor.

What is the use of @injectable in Angular?

The @Injectable() decorator defines a class as a service in Angular and allows Angular to inject it into a component as a dependency. Likewise, the @Injectable() decorator indicates that a component, class, pipe, or NgModule has a dependency on a service. The injector is the main mechanism.

Why would we use @injectable in a class?

Marking a class with @Injectable ensures that the compiler will generate the necessary metadata to create the class's dependencies when the class is injected.


1 Answers

Basically you're doing everything correct here:

import { Injectable } from '@angular/core';

export const AframeMessengerService = Injectable()(function AframeMessengerService() {
    console.log('aframe messenger');
});

Now you need to add this to module providers:

import { AframeMessengerService } from './a.service';

@NgModule({
  ...
  providers: [AframeMessengerService],
})
export class AppModule {}

And inject it like this:

import { AframeMessengerService } from './a.service';

@Component({
  selector: 'my-app',
  ...
})
export class AppComponent {   
  constructor(@Inject(AframeMessengerService) s) { }

One thing to note is that when you will be injecting services into AframeMessengerService you need to pass an index of parameter:

import { Inject, Injectable, Injector } from '@angular/core';

const AframeMessengerService = Injectable()(function AframeMessengerService(i) {
  console.log('aframe messenger');
});

Inject(Injector)(AframeMessengerService, null, 0);
                                         ^^^^^^^

export { AframeMessengerService };
like image 50
Max Koretskyi Avatar answered Oct 13 '22 00:10

Max Koretskyi