I want to retrieve an updated object value (borrower) from an Angular Service. I've created an RxJS Subject
in the Service so that multiple components can subscribe to it and get the updated value.
When I subscribe to the Subject through the provided service in the component, I find that the onNext()
function argument is never called even when .next()
is called from BorrowerService.
If I did subscribe within the BorrowerService class, I find that .next()
works as expected. It seems that the Subject is a different instance between the Service class that calls .next()
and the component, and so doesn't get that subscription.
Is this a failing in understanding Angular Services or Observables? How can I update the value in the Service and passively get the changes in the Component without it knowing when to call .next()
?
borrower-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);
}
}
The problem is the scope of your Service, and that a @ngModule
is not providing the service. If you want this to be a singleton service (same service instance for multiple components), then you will want to provide the service in a parent module that contains all the children components. For a guaranteed route, add this to your app.module.ts
. Import it in the module, and provide it as a service as you have in your component (remove it as a provider from your component, though... you only want the parent module to provide it).
You can then import the service into your component as you already have, and the provider
will be the parent module. The basic idea is the the parent module will host the service for all the children components, and therefore all the children components will receive the same instance of the service (and therefore the same values).
Side note: This SO Answer provides the details on creating a singleton service call ApiService
and should work as a solid guide. The other top answer provides a solid explanation as well.
Second note: If you want push updates from your subject, you will want want to use a BehaviorSubject as well. Subscriptions to BehaviorSubject will update automatically, while subscriptions to Subjects must be called manually.