I am aware that by using Ngrx and the Containers/Presentational components architecture the container-smart component should be the one which communicates with the store and basically passes data to the child components through their exposed Input properties. Also as a side note in the container component we are utilizing the OnPush change detection strategy.
The best option to achieve that, i suppose is to pass an observable to the template and unwrap it using async pipe. Something like
//in the container's component.ts file
this.file$ = this.store.pipe(takeUntil(this.destroy$), select(getFiles))
// in the container's html.ts
<child-component [sth] = 'files$ | async'
In most cases though this value is used again inside the container's ts file for various reasons and that's why i am forced to use something like
//in the container's component.ts file
this.store
.pipe(takeUntil(this.destroy$), select(getFiles))
.subscribe((files: Files[]) => {
this.files = files;
}
// in the container's html.ts
<child-component [sth] = 'files'
So that makes me to either
Inject the ChangeDetectorRef
in the Container and call the detectChanges
function as soon as i get a value from the observable stream.
Or
Implement the ngOnChanges
life-cycle hook in the child component to check when the input value changes.
I am wondering, Is there a better way to achieve this update by not having to use manually detectChanges all over the place or have to write this boilerplate code in the child components with ngOnChanges ?
Thanks.
Why do you need the files
value in your component?
Not knowing your use-case I think it's a bad practice (but it might be necessary in your case).
I prefer to let Angular handle subscriptions on its own with the async
pipe, to assign the local value you can use the tap
operator.
this.file$ = this.store
.pipe(
select(getFiles), // notice, we're not using takeUntil because Angular handles the subscription
tap(files => {
this.files = files; // assign the value here
})
)
Now you can use Observable as before:
<child-component [sth] = 'files$ | async'