For context:
I'm working on an Angular 15 app, where I distinguish between smart and dumb components. My smart components do have connection to services, whereas the dumb components only communicate via Inputs and Outputs with the smart component and do not get any services injected.
Within the smart components I use a reactive declarative (rxjs) approach to react to events. However, by now these smart components involve many reactive streams which makes the component bloated.
As these smart components are kind of "collectors" of many events and the "access" to the api service, I don't see reasonable way how I could break up the component into smaller parts.
Question:
I was thinking about using Design Patterns, e.g. the Facade Pattern, to declutter the component by putting the reactive streams into a separate service and the component would only have to subscribe to the final observables and handle the side effects (like UI updates).
However, I wonder if this would be a smart approach and if there are better ways to deal with this situation.
Example of complex smart component:
class MySmartComponent {
// ... several @Input and private members
// Multiple RxJS streams to handle different scenarios
dataFromRoute$: Data[] = this.route.url.pipe(/* ... */);
dataAfterAdded$: Data[] = this.addDataButtonClick$.pipe(/* ... */);
dataAfterMore$: Data[] = this.getMoreDataButtonClick$.pipe(/*...*/);
dataAfterDeleted$: Data[] = this.deleteDataButtonClick$.pipe(/* ... */);
data$: Observable<Data[]> = merge(
this.dataFromRoute$,
this.dataAfterAdded$,
this.dataAfterMore$
this.dataAfterDeleted$,
).pipe(/*...*/);
searchInput$ = new BehaviorSubject<string>(''); // user can search/filter Data
// subscription only to this Observable via async pipe in template!
filteredData$: Observable<Data[] | null> = combineLatest([
this.data$,
this.dataSearchInput$,
]).pipe(
// function calls by child components
onSearchInputChange(value: string) { /* ... */ }
onDeleteDataClick(event: SomeEvent) { /* ... */ }
// ... more logic
}
Generally using a separate service for managing data is a valid approach. You can create "MySmartService", make it non-singleton, and declare it as a provider for MySmartComponent. For example:
This way your MySmartService will only be created when
MySmartComponentis created. Also, you can addngOnDestroylifecycle hook toMySmartServiceto complete your data streams. It's going to work becauseMySmartServicewill be destroyed along withMySmartComponent.I wouldn't call it
Facadethought.Facadepattern is a structured API for several services or some complicated structure. In this case, we only have one component with different API calls / data streams.Perhaps it makes sense to create several additional services - one for API , one for user events, etc. So every service has one purpose and follows single responsibility principle.