Jacques
Jacques

Reputation: 3774

Angular 2 injecting a global dependency

What I would like to do is have a service that is available in every component, but I would prefer not having to import it into all of them. (Obviously, if I have to, I will.)

I thought, maybe incorrectly, that I could do something similar as when I bootstrap HTTP_PROVIDERS in my app which makes it available for HTTP (and is required if I'm not mistaken).

For example, in my app.ts file:

import { bootstrap } from 'angular2/platform/browser';
import { Injectable } from 'angular2/core';
import { HTTP_PROVIDERS } from 'angular2/http';
import 'rxjs/add/operator/map';
import { WidgetService } from './widget.service';
import { BuilderComponent } from './modules/builder/builder.component';

bootstrap(BuilderComponent, [HTTP_PROVIDERS, WidgetService]);

I was hoping that would make WidgetService available in all of the child/grandchild, etc, components. (BuilderComponent is a parent with several children/grandchildren.)

The error I am getting when using @Inject to inject it and @Injectable is not used in the service itself:

Uncaught ReferenceError: WidgetService is not defined

The error when using @Injectable in the service, and not using @Inject to inject it:

Cannot resolve all parameters for 'MyComponent'(NonGlobalService, ?). Make sure that all the parameters are decorated with Inject or have valid type annotations and that 'MyComponent' is decorated with Injectable.

I'm not sure why MyComponent needs to be decorated with Injectable, but I get the same error when I do decorate it with @Injectable.

widget.service.ts

import { Injectable, NgZone } from 'angular2/core';

@Injectable()
class WidgetService {
    constructor(private _zone: NgZone) {
    }
    // other methods here...
}

export { WidgetService };

And how I'm trying to inject it:

class MyComponent {
    constructor(private _nonGlobalService: NonGlobalService,
                private _widget: WidgetService) {
    }
}

To summarize:

  1. Can you globally inject a service into all components without importing it into every component manually. (IE: Make it available everywhere if I want it.)
  2. If you can, can someone explain what I'm doing wrong and tell me how to do it properly.
  3. Thank you for your time and answers!

Upvotes: 2

Views: 1910

Answers (1)

Günter Zöchbauer
Günter Zöchbauer

Reputation: 657148

There are different ways.

You can create a wrapper service and only inject this one.

@Injectable()
export class FooService {
  doFoo() {...};
}

@Injectable()
export class BarService {
  doBar() {...}
}

@Injectable()
export class GlobalService {
  constructor(public foo:FooService, public bar:BarService) {
  }
}

Here GlobalService needs to be imported

export class MyComponent {
  constructor(global:GlobalService) {
    global.foo.doFoo();
    global.bar.doBar();
  }
}

This way you don't need to import anything for the component

bootstrap(AppComponent, [
    provide('foo', { useClass: FooService }), 
    provide('bar', { useClass: BarService })]);

export class MyComponent {
  constructor(@Inject('foo') foo, @Inject('bar') bar) {
    foo.doFoo();
    bar.doBar();
  }
}

but I don't think this 2nd approach is adviceable. You won't get any IDE support because the type of the services isn't known within MyComponent.

Upvotes: 1

Related Questions