This answer is based on the answers provided by FlavorScape and by mahyar.
No external libraries solution
One way to avoid bloating each component with the subject and its code is to use a base component (tested with Angular 10.0.6):
base.component.ts
import { Subject } from "rxjs";
import { Component } from "@angular/core";
@Component({
selector: "app-base-component",
template: ""
})
export class BaseComponent {
public ngDestroyed$ = new Subject();
public onDestroy(): void {
this.ngDestroyed$.next();
}
}
foo.component.ts
@Component({
selector: "app-foo",
templateUrl: "./foo.component.html",
styleUrls: ["./foo.component.scss"]
})
export class FooComponent extends BaseComponent implements OnInit, OnDestroy {
fooList$: Observable<FooModel[]>;
@ViewChild(DataBindingDirective) dataBinding: DataBindingDirective;
public gridData: any[];
public gridView: any[];
public mySelection: string[] = [];
constructor(private readonly store: Store<AppState>) {
super();
}
ngOnDestroy(): void {
this.onDestroy();
}
ngOnInit(): void {
this.store.dispatch(ApplicationFooItemsRequestedAction());
this.fooList$ = this.store.select(selectAllApplicationFooItems);
this.fooList$.pipe(takeUntil(this.ngDestroyed$)).subscribe(ul => {
// do stuff with items
});
}
}
Using an external library
You can use @ngneat/until-destroy library to avoid custom code and also support other scenarios (e.g. within services)
@Component({
selector: "app-foo",
templateUrl: "./foo.component.html",
styleUrls: ["./foo.component.scss"]
})
export class FooComponent extends BaseComponent implements OnInit, OnDestroy {
ngOnInit(): void {
this.store.dispatch(ApplicationFooItemsRequestedAction());
this.fooList$ = this.store.select(selectAllApplicationFooItems);
this.fooList$.pipe(takeUntil(untilDestroyed(this))).subscribe(ul => {
// do stuff with items
});
}
}