In his article Presentational and Container Components, Dan Abramov discusses separating presentational and container components in React. The idea is general and separating Angular components in a similar manner is an approach that some developers choose to take.
With Angular, the separation of container and presentational components gets interesting when Reactive Forms are added to the mix. A reactive form introduces an observable, subscriptions to which receive notifications of the form’s — or one of its controls’ — changed values. The notifications make it easy to implement features like debounced searches using RxJS. However, if such features are implemented in presentational components, they will no longer be purely presentational.
How can Reactive Forms be used without compromising the simplicity of presentational components? Let’s look at a solution that uses RxJS.
Usually, presentational components communicate with container components using an
Output property that’s an
EventEmitter. However, when using Reactive Forms, that would involve converting the notifications received from the form’s
valueChanges observable to events. And, in the container component, to be used with an observable service, the events would need to be converted back into an observable. That seems complicated.
Instead, the presentational component could accept an
Input observer that could be subscribed to the
valueChanges observable. In fact, it can accept a
PartialObserver, as there is no particular requirement for the observer to implement
A presentational component that displays a list of GitHub users with usernames that start with a typed-in value would look something like this:
The component accepts an observer and an array of users — the results of the search. It subscribes the observer to the form’s
valueChanges, mapping the observable’s form values to the typed-in username. And it displays the users in a list.
The container component would look something like this:
The container component passes a
Subject to the presentational component — to receive the notifications for the changes to the typed-in username. Subjects are both observers and observables, so the
users observable can be composed directly from the subject.
The service injected into the container component would implement a
searchUsers method, something like this:
With this arrangement, the typed-in values will flow from the presentational component’s reactive form, to the container component’s subject, where they will be debounced and then passed to the search service. The users returned from the service will then flow back to the presentational component, where they will be received as an array of
User entities due to the
async pipe used in the container component.
Using subjects to connect observables in this manner is something that happens a lot in RxJS. In fact, it’s how some operators — like
share — are implemented.
If you are interested in reading more about subjects and their uses, Ben Lesh’s On the Subject of Subjects (in RxJS) is a good place to start.
This post is also published on my personal blog: ncjamieson.com.