Sharing data between Angular components usually means juggling @Input and @Output decorators and hoping you wired them in the right order. There is a cleaner route, and it sits inside RxJS. A Subject observable lets components publish and subscribe to the same data stream without parent-child plumbing.
The approach is straightforward: create a service with a private Subject, expose an observable for subscribers, and let any component push or listen for changes. For developers building apps with multiple screens that need to stay in sync, this pattern eliminates the need to thread data down through layers of intermediate components.
- A Subject acts as both observer and observable—one source, many subscribers.
- The service exposes sendMessage to publish data and accessMessage to return an observable.
- Child components subscribe in ngOnInit and unsubscribe in ngOnDestroy to avoid memory leaks.
- The pattern works for any number of subscribers without changing the sender.
How the pattern works
The implementation creates message.service.ts with a private Subject instance. A sendMessage method calls subject.next(msg) to push data out. An accessMessage method returns subject.asObservable() so other components can subscribe without direct access to the Subject itself.
In the app component, a text input and button call msgService.sendMessage(this.msg). In the child component, ngOnInit subscribes to the observable and pushes incoming messages into a local list, while ngOnDestroy calls subscription.unsubscribe() to clean up.
Why this beats @Input and @Output for some cases
@Input and @Output force a strict parent-child relationship. The Subject pattern decouples the sender and receiver completely. A component on one branch of the tree can publish a message that a sibling, cousin, or distant descendant consumes without any new wiring.
The catch is lifecycle management: forget to unsubscribe and you leak memory, because the observable stays live after the component is gone.
Our analysis
The Subject pattern is one of three common Angular sharing tools. BehaviorSubject is better when you need new subscribers to immediately receive the current value. ReplaySubject buffers a history. A plain Subject is the right pick when each message is a one-shot event, which is exactly what this pattern demonstrates with its message list.
For apps with deep navigation or multiple unrelated screens, this pattern shines. A settings screen can publish a theme change, and every listening component updates without the settings page needing to know who is listening.
One caveat: the tutorial's sendMessage and accessMessage methods lack TypeScript typing. In a real codebase, type both the message payload and the observable. It takes two minutes and saves hours of debugging later.
Who should care
| Scenario | Recommended pattern |
|---|---|
| Simple parent-child data flow | @Input/@Output |
| One-shot events between unrelated components | Subject |
| Need latest value on subscription | BehaviorSubject |
| Need buffered history of values | ReplaySubject |
| Complex state across many features | NgRx or similar |
Say you are building an in-app notification bell
You have a header component with a bell icon and a settings page where users toggle alerts. Create a NotificationService with a private Subject. The settings page calls notificationService.push(prefs) when the user saves. The bell component subscribes in ngOnInit, unsubscribes in ngOnDestroy, and updates its badge count from the stream. No parent-child wiring, no event emitters hopping through intermediaries, and you can add more subscribers later without touching the publisher.
Bottom line
The Subject pattern is a workhorse for Angular event streams. Use it for fire-and-forget updates, type your payloads, and always unsubscribe in ngOnDestroy.
Key takeaways
- Use Subject for one-shot events; reach for BehaviorSubject when new subscribers need the current value.
- Always unsubscribe in ngOnDestroy to prevent memory leaks.
- Type your message payload and the observable for safer code.
- Keep the Subject private and expose only asObservable() to consumers.
Frequently asked questions
What is the difference between a Subject and a BehaviorSubject?
A Subject only emits to subscribers that exist when the value is published. A BehaviorSubject stores the latest value and replays it to any new subscriber.
Why do I need to unsubscribe from a Subject?
Without unsubscribing, the subscription stays alive after the component is destroyed, holding a reference to it and causing memory leaks.
Can multiple components subscribe to the same Subject?
Yes. Subject is multicast, so any number of components can subscribe and each will receive every emitted value.
Is the Subject pattern better than using a state management library?
For small to mid-size apps, yes. For complex state shared across many features, a library like NgRx is usually a better fit.