Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to share data between components using service in Angular 17

I want to share a value between all my components (which are not necessarily related) using a service.

There are a number of examples online but it doesn’t work for me, I don’t know what I did wrong.

Also, many examples are based on old versions of Angular whereas I would like to use modern methods to do it.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

For now I have this 3 files, and I want to share a "Theme" value :

theme.service.ts :

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

@Injectable({
  providedIn: 'root'
})
export class ThemeService {
  private _theme: 'light'|'dark' = 'light';

  public get Theme() {
    return this._theme;
  }
  public set Theme(theme: 'light'|'dark') {
    this._theme = theme;
  }

  constructor() { }
}

app.component.ts :

import { Component, AfterViewInit } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { ThemeService } from './services/theme.service';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [RouterOutlet],
  providers: [ThemeService],
  templateUrl: './app.component.html',
  styleUrl: './app.component.scss'
})
export class AppComponent implements AfterViewInit {

  constructor(private themeService: ThemeService) { }

  ngAfterViewInit() {
    console.log("app.component:", this.themeService.Theme);
    this.themeService.Theme = "dark";
    console.log("app.component:", this.themeService.Theme);
  }
}

mycomponent.component.ts :

import { Component, ElementRef, ViewChild, AfterViewInit } from '@angular/core';
import { ThemeService } from '../../services/theme.service';

@Component({
  selector: 'app-mycomponent',
  standalone: true,
  imports: [],
  providers: [ThemeService],
  templateUrl: './mycomponent.component.html',
  styleUrl: './mycomponent.component.scss'
})
export class MyComponent implements AfterViewInit {

  constructor(private themeService: ThemeService) { }

  ngAfterViewInit() {
    console.log("mycomponent.component:", this.themeService.Theme);
  }
}

I would like to have this result:

app.component: light
app.component: dark
mycomponent.component: dark

But I have this:

app.component: light
app.component: dark
mycomponent.component: light

I imagine that the two components are using different instances of the service, how do I make it so that the service is shared between the two?

>Solution :

Don’t add ThemeService to your components’ providers arrays. The service is already providedIn: 'root' which means you already have a singleton for the application. If you add the service to the providers array for the component, you’ll create a second copy that only that component knows about.

See the Dependency injection and injectors hierarchy section of the Getting started with standalone components guide (emphasis mine):

Angular applications can configure dependency injection by specifying a set of available providers. In a typical application, there are two different injector types:

  • module injector with providers configured in @NgModule.providers or @Injectable({providedIn: "..."}). Those application-wide providers are visible to all components in as well as to other services configured in a module injector.
  • node injectors configured in @Directive.providers / @Component.providers or @Component.viewProviders. Those providers are visible to a given component and all its children only.
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading