2
votes

I have a simple component progressBar in order to display (or not) the progress bar. And a simple observable service.

Here is the service :

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

@Injectable() 
export class ProgressBarService {
  subject = new BehaviorSubject<any>(false);
  changes = this.subject
              .asObservable()
              .do(changes => console.log('new state', changes)); 

  constructor(private http: Http) {
  }
  show() {
    this.subject.next(true);
  }
  hide() {
    this.subject.next(false);
  }
}

Nothing fancy here, just a BehaviorSubject which is set by default with false, hide/show is used to change the value with .next().

The component looks like this :

import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import { ProgressBarService } from './progressbar.service';

@Component({
  selector: 'app-progressbar',
  templateUrl: './progressbar.component.html',
  styleUrls: ['./progressbar.component.scss'],
  providers:[ProgressBarService]
})

export class ProgressbarComponent implements OnInit {

  isDisplay : boolean;

  constructor(private $progressbar : ProgressBarService) { }

  ngOnInit() {
    this.$progressbar
      .changes
      .subscribe((display : boolean) => this.isDisplay = display);
  }

  showProgress(){
    (this.isDisplay)
      ? this.$progressbar.hide()
      : this.$progressbar.show();
  }
}

During the init, the component subscribe to the subject in order to get the default value and set it to isDisplay. showProgress is only used to try it in my template.

<md-progress-bar mode="indeterminate" color="accent" *ngIf="isDisplay"></md-progress-bar>

<button type="submit" md-raised-button color="primary" (click)="showProgress()">Show/hide progressBar</button>

And it works just fine when the service is used inside the component.

But, when I try to call this service inside another component, it doesn't work.

Example : My other component called profilesComponent

import { ProgressBarService } from ../progressbar/progressbar.service';

@Component({
  selector: 'profiles',
  templateUrl: 'profiles.component.html',
  providers: [ProgressBarService]
})

export class ProfilesComponent implements OnInit {

  toto :boolean = false;

  constructor(private $progressbar : ProgressBarService) {}

  ngOnInit() {}

  showProgress() {
    if(this.toto) {
      this.$progressbar.hide();
      this.toto = false; 
    } else {
      this.$progressbar.show();
      this.toto = true;
    }
  }
}

I think it's because the two component does not share the same instance of the service but i can't find a way to do so. (Maybe providers in @NgModule?)

1
Yes this could be a reason. declare it in NgModule and remove from both components.micronyks
Holy **** ! You're right, it's the reason. I removed the ProgressBarService from the provider's components then I added it to app.module.js. Now they both share the same instance and it works ! Well, thank you sir. I just understood a thing tonight :)ByJC
Great !!! enjoy Angular2 then !micronyks

1 Answers

2
votes

Thanks to @micronyks, Here is the solution.

For each component, I add the service in the provider's component. In result, the components create a new instance of the service.

In order to resolve the issue, i removed the service from the providers of each component then provide it to the main module.

import { ProgressBarService } from './progressbar/progressbar.service';

@NgModule({
  imports: [
    CommonModule,
    BrowserModule,
    HttpModule,
    AppRoutingModule,
    HomeModule,
    MaterialModule.forRoot()
  ],
  declarations: [AppComponent, ProgressbarComponent],
  providers: [ProgressBarService],
  bootstrap: [AppComponent],
})
export class AppModule { }

The components now share the same instance and the progress bar is well displayed.