Marco Jr
Marco Jr

Reputation: 6806

Angular 2 - Using Shared Service

Looks like shared services is the best practice to solve many situations such as communication among components or as replacement of the old $rootscope concept of angular 1. I'm trying to create mine, but it's not working. Any help ? ty !!!

app.component.ts

import {Component} from 'angular2/core';
import {OtherComponent} from './other.component';
import {SharedService} from './services/shared.service';
@Component({
selector: 'my-app',
providers: [SharedService],
directives: [OtherComponent],
template: `
    <button (click)="setSharedValue()">Add value to Shared Service</button>
    <br><br>
    <other></other>
`
})
export class AppComponent { 
data: string = 'Testing data';
setSharedValue(){
    this._sharedService.insertData(this.data);
    this.data = '';
    console.log('Data sent');
}
constructor(private _sharedService: SharedService){}
}

other.component.ts

import {Component, OnInit} from "angular2/core";
import {SharedService} from './services/shared.service';
@Component({
selector : "other",
providers : [SharedService],
template : `
I'm the other component. The shared data is: {{data}}
`,
})
export class OtherComponent implements OnInit{
data: string[] = [];
constructor(private _sharedService: SharedService){}
ngOnInit():any {
    this.data = this._sharedService.dataArray;
}
}

Upvotes: 11

Views: 32676

Answers (3)

In addition to your requirement and its solution, you can consider using Facade + Shared Services. I have a small project here: https://github.com/cmandamiento/angular-architecture-base

Upvotes: 1

Oswaldo Alvarez
Oswaldo Alvarez

Reputation: 4812

You need to add a global provider in your module, then you dont need to add this provider in each component. try this

app.module.ts

@NgModule({
    imports: [BrowserModule, FormsModule, HttpModule],
    declarations: [AppComponent, LoginComponent, InComponent],
    providers: [LoginService],
    bootstrap: [AppComponent]
})

app.component.ts

@Component({
    moduleId: module.id,
    selector: 'app',
    templateUrl: './app.component.html'
})
export class AppComponent {
    constructor(public loginService: LoginService) {

    }
}

login.component.ts

@Component({
    moduleId: module.id,
    selector: 'login',
    templateUrl: './login.component.html'
})
export class LoginComponent {

    constructor(public loginService: LoginService) {

    }
}

I hope this work for you.

Upvotes: 4

Thierry Templier
Thierry Templier

Reputation: 202326

Most of time, you need to define your shared service when bootstrapping your application:

bootstrap(AppComponent, [ SharedService ]);

and not defining it again within the providers attribute of your components. This way you will have a single instance of the service for the whole application.


In your case, since OtherComponent is a sub component of your AppComponent one, simply remove the providers attribute like this:

@Component({
  selector : "other",
  // providers : [SharedService], <----
  template : `
    I'm the other component. The shared data is: {{data}}
  `,
})
export class OtherComponent implements OnInit{
  (...)
}

This way they will shared the same instance of the service for both components. OtherComponent will use the one from the parent component (AppComponent).

This is because of the "hierarchical injectors" feature of Angular2. For more details, see this question:

Upvotes: 9

Related Questions