Louise
Louise

Reputation: 573

Update data of service from multiple components - Observable subscribe

I want show the title of page in a fixed Navbar file after enter to each page of the site

Files structure:

-navbar.ts         (where I display the title, import current title from service)
-titles.service.ts (store the current title )
-component_one.ts  (Send title 1 to service)
-component_two.ts  (Send title 2 to service)

navbar.ts file

import { Component, OnInit,} from '@angular/core';
import { Subscription } from "rxjs";
import {TitleService} from './titles.service';
import {component_one} from '../component_one';
import {component_two} from '../component_two';


@Component({
selector: '[navbar]',
template: require('./navbar.html'),
providers:[TitleService, component_one, component_two]
})

export class Navbar implements OnInit {
 title_page: any;
 _subscription: any;

 constructor(public com_one: component_one, public _titleService:TitleService,  public com_two: component_two){

  this.title_page = _titleService.title_page;
  this._subscription = _titleService.titleChange.subscribe((value) => { 
    this.title_page = value; 
  });  //it's ok?

  }

 ngOnDestroy() {
   this._subscription.unsubscribe();
 }
}

titles.service.ts

import {Component, Injectable } from '@angular/core';
import { Http, Headers, Response } from '@angular/http';
import { Subject } from 'rxjs/Subject';
import { Subscription } from "rxjs";


@Injectable()
export class TitleService {
  title_page: any;


  titleChange: Subject<string> = new Subject<string>(); //it is ok?

  constructor() {
  this.title_page = "default title string"; 
  }

  change(title){
  this.title_page = title;
  this.titleChange.next(this.title_page);  //I think is not working
  }
}

component_one.ts file (after load this page, I want show 'TITLE OF COMPONENT ONE' on navbar html file )

import {Component} from '@angular/core';
import {TitleService} from '../core/navbar/titles.service';

@Component({
selector: '[component_one]',
template: require('./component_one.html')
providers: [TitleService]
})

export class component_one{
title_page: any;

  constructor(public http: Http, public _titleService: TitleService){
   this.title_page = _titleService.title_page;
   this.changeMyTitle(); //Update Title
  }

  changeMyTitle() {
  this._titleService.change('TITLE OF COMPONENT ONE');
  }

}

component_two.ts file (same as component_one with different title string,after load this page, I want show 'TITLE OF COMPONENT two' on navbar html file )

import {Component} from '@angular/core';
import {TitleService} from '../core/navbar/titles.service';

@Component({
selector: '[component_two]',
template: require('./component_one.html')
providers: [TitleService]
})

export class component_two{
title_page: any;

  constructor(public http: Http, public _titleService: TitleService){
   this.title_page = _titleService.title_page;
   this.changeMyTitle(); //Update Title
  }

  changeMyTitle() {
  this._titleService.change('TITLE OF COMPONENT TWO');
  }

}

After enter to first page (component one) still showing 'TITLE OF COMPONENT TWO', what I am doing wrong?

Upvotes: 1

Views: 915

Answers (1)

eko
eko

Reputation: 40647

If you use your TitleService inside every components providers part, it will create a new instance of that service (providers: [TitleService])

So don't do this:

@Component({
selector: '[component_one]',
template: require('./component_one.html')
providers: [TitleService]
})

Instead move the service to @NgModule providers so that every component inside that module will have the same instance of the providers:

@NgModule({
  imports: [ BrowserModule ],
  providers: [MyService]
  declarations: [ App, AnotherApp ],
  bootstrap: [ App ]
})

Full example:https://plnkr.co/edit/qMnXG7oxF3SdTptKHUen?p=info

For older versions,

Put the shared service in the bootstrap function to share it across the app:

bootstrap(App, [MyService]);

Upvotes: 3

Related Questions