2017-10-06 3 views
1

Je souhaite récupérer une valeur d'objet mise à jour (emprunteur) à partir d'un service Angular. J'ai créé un RxJS Subject dans le Service afin que plusieurs composants puissent s'y abonner et obtenir la valeur mise à jour.Service angulaire avec objet Appel visible next() non vu par les abonnements aux composants

Quand je souscris au sujet à travers le service fourni dans le composant, je trouve que l'argument de la fonction onNext() est jamais appelé même quand .next() est appelé à partir BorrowerService.

Si je me suis abonné à la classe BorrowerService, je trouve que .next() fonctionne comme prévu. Il semble que le sujet est une instance différente entre la classe Service qui appelle .next() et le composant, et n'obtient donc pas cet abonnement.

Est-ce un défaut de compréhension des Services Angulaires ou Observables? Comment est-ce que je peux mettre à jour la valeur dans le service et obtenir passivement les changements dans le composant sans savoir quand appeler .next()?

emprunteur-report.component.ts

@Component({ 
    ... 
    providers: [BorrowerService] 
}) 
export class BorrowerReport { 
    private borrower: Borrower; 

    constructor(private borrowerService: BorrowerService) { 
     this.borrowerService.borrowerChanged.subscribe(borrower => {this.borrower = borrower}); 
    } 
} 

borrower.service.ts

@Injectable() 
export class BorrowerService { 
    public borrowerChanged: Subject<Borrower> = new Subject<Borrower>(); 

    //event handler 
    selectBorrower(borrower: Borrower) { 
     this.borrowerChanged.next(borrower); 
    } 
} 
+1

https://stackoverflow.com/q/42567674/5394220 dup –

Répondre

3

Le problème est la portée de votre service, et @ngModule ne fournit pas le service. Si vous voulez que ce soit un service singleton (même instance de service pour plusieurs composants), vous devez fournir le service dans un module parent qui contient tous les composants enfants. Pour un itinéraire garanti, ajoutez-le à votre app.module.ts. Importez-le dans le module et fournissez-le en tant que service comme vous l'avez dans votre composant (supprimez-le en tant que fournisseur de votre composant, mais ... vous voulez seulement que le module parent le fournisse).

Vous pouvez ensuite importer le service dans votre composant comme vous l'avez déjà fait et provider sera le module parent. L'idée de base est que le module parent hébergera le service pour tous les composants enfants, et donc tous les composants enfants recevront la même instance du service (et donc les mêmes valeurs).

Note secondaire: This SO Answer fournit les détails sur la création d'un appel de service singleton ApiService et devrait fonctionner comme un guide solide. L'autre meilleure réponse fournit également une explication solide.

Deuxième remarque: Si vous voulez pousser les mises à jour à partir de votre sujet, vous voudrez également utiliser un BehaviorSubject. Les abonnements à BehaviorSubject seront mis à jour automatiquement, tandis que les abonnements à Subjects doivent être appelés manuellement.

1

compte les éléments suivants:

borrower.service.ts

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


@Injectable() 
export class BorrowerService { 

    public borrowerChanged = new BehaviorSubject<string>('Defaut Value'); 
    borrowerChangedObservable = this.borrowerChanged.asObservable(); 
    constructor(){} 

    changeValue(value: string): void { 
    this.borrowerChanged.next(value); 
    } 
} 

puis dans votre composant:

emprunteur-report.component.ts

pour obtenir les valeurs que vous faites:

constructor(private borrowerService: BorrowerService) { 
    this.borrowerService.borrowerChangedObservable 
     .subscribe((borrower) => { 
       console.log(borrower); 
      }); 
    } 

pour définir une nouvelle valeur que vous faites :

sendNewValueToBorrowerService(){ 
this.borrowerService.changeValue('my new value'); 
} 

et n'oubliez pas d'ajouter le service dans le tableau provides et le composant dans le tableau des déclarations du même module.