Search code examples
angularangular8angular-servicesangular-module

Subscribe function is not trigger when I call function next on BehaviourSubject


I have 2 components and one service shared between the 2 components, let's say ComponentA and ComponentB. One component in for the toolbar of the app (Comp. A) and the other one, component B, is routed with the routing module. This is the HTML:

<a></a>
<router-outlet></router-outlet>

It is in this way because I want to always have the toolbar present, fixed, at the top. In the HTML for component A, I have a select to select the language of the app. In Component B I have some content that comes from backend depending on the selected language.I want that when the user changes the language, the content came from server, to be rendered.I am using the service to call the backend and render the new content. Here comes my problem, the call to server is done and is ok, but it never enters to the subscription function. I have tried to use a shared module (with or without forRoot()), I tried to make the service a provider for a module, and import the module(AppRoutingModule) in the other module(AppModule). In this moment I got to the point where I have the "No provider for Service!" error in console. The code for service and components: Service:

@Injectable()
export class SharedService extends GlobalHttpService<HomeSection> {
  private sectionsSubject: BehaviorSubject<HomeSection[]>;
  constructor(private http: HttpClient) {
    super("api/path", new GlobalSerializer(HomeSection), http);
    this.sectionsSubject = new BehaviorSubject<HomeSection[]>([]);
  }

  load() {
    this.list().subscribe(res => {
      this.sectionsSubject.next(res);
    });
  }
  get content() {
    return this.sectionsSubject.asObservable();
  }
}

AppModule

@NgModule({
 imports:[AppRoutingModule]
})
export class AppModule {}

AppRoutingModule

export function SharedServiceFactory(http: HttpClient){
  return new SharedServiceFactory(http);
}

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
  providers: [
    {
      provide: SectionService,
      useFactory: SectionServiceFactory,
      deps: [HttpClient]
    }
  ]
})
export class AppRoutingModule {}

ComponentA:

@Component({
  selector: "a",
  templateUrl: ".a.component.html",
  styleUrls: ["./a.component.scss"]
})
export class AComponent implements OnInit {
  constructor(
    public authentificationService: AuthenticationService,
    private languagesService: LanguagesService,
    private sharedService: SharedService
  ) {
  }
 ngOnInit() {
//other logic;
}

updateLanguage(event) {
// other logic;
this.sharedService.load();
}

ComponentB

@Component({
  selector: "app-b",
  templateUrl: "./b.component.html",
  styleUrls: ["./b.component.scss"]
})
export class BComponent implements OnInit {
  constructor(
    private sharedService: SharedService,
  ) {}

ngOnInit() {
 this.sharedService.load();
 this.sharedService.content.subscribe(s => {
 // logic
 });
}

How can I make to have a single instance of the SharedService or can I include one module in another?


Solution

  • Try to do this in your service:

    @Injectable({ providedIn: 'root' })
    

    And remove providing of this service from AppRoutingModule. If you use providedIn: 'root' you do not need to provide it somewhere else. It will inject the service at very top of Angular tree, so you will always have the same instance. Another benefit from it - it makes services tree-shakeable.