2

I'm little confused about singleton services on Angular 2. I need a translate service in whole application, and I want there is only one instance of the service. I have two buttons to switch the language. When i run the app, I use a pipe to translate content and it works, but the switch buttons don't work. I get an error message:

self.parent.context.use is not a function'.

I guess it's all about some misunderstood about some angular concepts so, anyone can help me to implement a global service correctly?

//Translation service
@Injectable()
export class TranslateService {
  private _currentLang: string;

  constructor(){
    this._currentLang = 'es';
  }

  public get currentLang() {
    return this._currentLang;
  }

  public use(lang: string): void {
    // set current language
    this._currentLang = lang;
  }

  private translate(obj : LocalizedData): string {
    // private perform translation
    return obj[this._currentLang];
  }

  public instant(obj: LocalizedData ) {
  // call translation
    return this.translate(obj); 
  }
}

//Navbar Module
@NgModule({
  imports:      [ CommonModule, FormsModule],
  declarations: [ NavbarMenuComponent, TranslatePipe],
  exports: 		[ NavbarMenuComponent]
})

export class NavbarModule { }

//App component
@Component({
  selector: 'app',
  template:'<navbar-menu ></navbar-menu>'
})

export class AppComponent implements OnInit{
  public translatedText : string;
    constructor(){}
    ngOnInit(){}
  }

//app Module
@NgModule({
  imports:      [ BrowserModule, FormsModule, NavbarModule],
  declarations: [ AppComponent],
  bootstrap:    [ AppComponent],
  providers: 	[ TranslateService],
})

export class AppModule { }


//Main
const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule,[ TranslateService]);
 

2
  • All services are singletons by default in angular2. From the documentation Singleton services. Dependencies are singletons within the scope of an injector. Commented Oct 24, 2016 at 10:55
  • You should either provide something that runs with instruction on exactly where to look OR provide a Minimal, Complete, and Verifiable example with a focus on Minimal. Providing all your code like above adds too much noise to your question. Commented Oct 24, 2016 at 11:07

1 Answer 1

3

In Angular2 services are singletons per provider. If you provide a service multiple times, you'll get multiple instances.

If you provide it in

@NgModule({ 
  providers: [SomeService]
  ...
})

then it will be provided at the root scope and you'll get a single instance for your whole application. Even when more than one @NgModule() contains a service in providers, you'll get only one instance because they are hoisted in the application root scope.

Lazy loaded modules have their own root scope.

If you provide a service in @Component() every such component instance and it's children will get a different service instance.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for response! That was what I undestood from the documentation but then, if I provide the service on the root module 'AppModule', how can I call the service on child modules and templates? I'ts posible do it without injecting the service on each component constructor? If I only provide the service to the root module I get the same error..
Providing only defines the scope of the service. To use it you have to inject it using a constructor parameter.
@GünterZöchbauer Is there any way to get around having to write import x from y at the top of every file also? I'd like to have lodash as a global variable.
I'm not actively usimg TS myself. You need to import everything you use, no way around it. You can simplify a bit using for example barrels, but they come with their own problems

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.