Ionic 4 - Service at root


#1

Hi,

I’m trying to have a service that could be shared across my pages.
I’ve imported it in the providers but it still create a new instance on every page the service is called.
I’ve created a sharedmodule, imported only at app.module… same issue.

Did anyone face the same issue ? Or did you manage to get around it ?

Thanks !


#2

Hi @Nanex!

You can specify just that in your service, and import it once in AppModule:

@Injectable({
  providedIn: 'root'
})

Best,
Rodrigo


#3

Thanks @Rodrigo but it doesn’t work for me. I am using the service automatically generated by CLI which includes this decoration and after including the service in the app module and in the constructor of the page, I am always getting 2 different instances of the service whenever I am going from one page to another…


#4

Can you share the contents of your AppModule, the service and the page where you’re trying to use it? How have you determined that they are different instances of the service?


#5

Sure, thanks for your help !

App Module :

import { ShareModule } from './share/share.module';

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';

import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';

@NgModule({
  declarations: [AppComponent],
  entryComponents: [],
  imports: [ BrowserModule, ShareModule.forRoot(), IonicModule.forRoot(), AppRoutingModule ],
  providers: [
    StatusBar,
    SplashScreen,
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

Service :

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

@Injectable({
  providedIn: 'root'
})
export class GeneService {

  uid;
  new;
  
  constructor() { 
    this.uid = Date.now()
  }
}

homepage :

import { GeneService } from './../gene.service';
import { Component } from '@angular/core';

@Component({
  selector: 'app-home',
  templateUrl: 'home.page.html',
  styleUrls: ['home.page.scss'],
})
export class HomePage {
  constructor(public _g: GeneService){

    this._g.new = 'bonjour';
  }
}

test page :

import { GeneService } from './../gene.service';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-test',
  templateUrl: './test.page.html',
  styleUrls: ['./test.page.scss'],
})
export class TestPage implements OnInit {

  constructor(
    public _gen: GeneService
  ) {
    console.log(_gen.new);
  }

  ngOnInit() {
  }

}

I tried the approach of a shared service module :

import { NgModule, ModuleWithProviders, Optional, SkipSelf } from '@angular/core';
import { GeneService } from './../gene.service';

@NgModule({})
export class ShareModule {
  
  constructor (@Optional() @SkipSelf() parentModule: ShareModule) {
    if (parentModule) {
      throw new Error(
        'CoreModule is already loaded. Import it in the AppModule only');
    }
  }

  static forRoot(): ModuleWithProviders{
    return {
      ngModule: ShareModule,
      providers: [ GeneService ]
    };
  }
 }

I’ve tried everything but everytime I get the same, the first page init the variable new with bonjour, but the other page doesn’t get the new value and the date number is a new one … I’m desperate to know what I do wrong :frowning:

Thanks again !


#6

Try importing the GeneService in the AppModule and including it at the end of the providers array :wink:


#7

Done that as well and doesn’t make a difference.


#8

You should not use new as a variable name as that’s a reserved word in JavaScript (and so is also one in Typescript). That’s because you would use it to create a class instance. e.g. let a = new Array();


#9

You are totally right but your comment doesn’t help. I use dummy variable to test and the result is always the same with any variable name.


#10

I’ve posted on github a test project to illustrate the issue : https://github.com/lenanex/IonicLazyWithCentralService/tree/master/src/app

If anyone has any guidance on how to ensure the service will be shared across modules without creating a new instance whenever the module is lazy loaded, it would be great !

Thanks !!


#11

Stupid mistake on my side, apologies for the wasted time on your side @FdezRomero and @sjwestern.

Implementing the service in the app.module in providers works perfectly well if you are using router-link or Navcontroller of Ionic and not the simple url in a Href (like I did).


#12

No worries! We all have to learn at some point :wink: