Share data between components using a service in Angular2

camaron is right. Your mistake is that you declare UtilityService twice:

  1. Once in the providers of SearchComponent.
  2. Once in the providers of TransferComponent.

You should declare the service ONLY ONCE to make sure both components get the same instance. For this you can choose between either of these options:

  1. Declare the service in the providers of a @NgModule which has both SearchComponent and TransferComponent in its declarations. 9 times out of 10 this is the right solution!
  2. Declare the service in the providers of a @Component which is a parent of both SearchComponent and TransferComponent. This might not be feasible depending how your component tree looks.

Following option #1, you end up with:

@NgModule({
  imports: [CommonModule, ...],

  // Look, the components injecting the service are here:
  declarations: [SearchComponent, TransferComponent, ...],

  // Look, the service is declared here ONLY ONCE:
  providers: [UtilityService, ...]
})
export class SomeModule { }

Then inject UtilityService in your components' constructors WITHOUT REDECLARING IT in the components's providers:

@Component({
  selector: 'foo',
  template: '...',
  providers: []  // DO NOT REDECLARE the service here
})
export class SearchComponent {
  constructor(private utilityService: UtilityService) { }
}

@Component({
  selector: 'bar',
  template: '...',
  providers: []  // DO NOT REDECLARE the service here
})
export class TransferComponent {
  constructor(private utilityService: UtilityService) { }
}

You need to distinguish when service is from NgModule, or when it comes from other Component.

Basics

In Angular2 you have a hierarchical tree of components with parent-child relation (as you noticed). At the same time all services are injected with help of injectors, which also form a hierarchy tree (in parallel to component hierarchy). The tree of injectors do not necessary coincide with component tree, as there could be proxy injectors from parent for efficiency purposes.

How it works

The role of the injectors is to take the service you define in constructor and inject it into your component, i.e. find it, initiate if not found and provide it to you. When you put into constructor that you want some service, it will go look into injector tree from your component up to the root (which is NgModule) for service existence. If injector finds that there is a defined provider for this service but no service instance, it will create the service. If no provider it continues to go up.

What you have seen so far

What you have seen is that the parent component defines through "providers" the service, and injectors in search for the service goes one hop up in the tree, finds the provider, initiate service and gives to your child component. In order for all components of some subtree to have the same Service, you need to define provider only in the common root of the subtree. If you want to have same service for whole module, you need define this service in providers of module. This is so-called Singleton service.

Some extra

Normally if you want to inject service and could not find it all the way up to root, you will get error during compilation/runtime. But if you define that you want to inject Optional service, injector will not fail if the provider for this service is not found.

More or less...

Some useful links:

  1. https://angular.io/docs/ts/latest/guide/hierarchical-dependency-injection.html

  2. https://blog.thoughtram.io/angular/2015/05/18/dependency-injection-in-angular-2.html