I have an angular component which gets data from an @Input variable and uses this to filter additional data from a service. The (simplified) structure looks like this:
<phones-component>
<phone-details>
<..>
<phone-history-component [phoneNumber$]="phoneNumber$"></phone-history-component>
<phone-details>
</phones-component>
PhoneDetailsComponent:
changeLogs$: Observable<AuditLog[]>;
constructor(
private auditLogService: AuditLogService, //ngrx-data service
){
ngOnInit(): void {
this.changeLogs$ = combineLatest([this.phoneNumber$, this.auditLogService.entities$])
.pipe(
map(pn => pn[1].filter(logs => logs.pkId === pn[0].id))); //filters the logs to show only log entries from the corresponding phonenumber
}
The routes are configured like this:
{
path: 'phones',
component: PhonesComponent,
},
{
path: 'phones/:id',
component: PhoneDetailsComponent,
},
Everything works as expected as long as I 'enter' the PhoneDetailsComponent from the parent container. When the user manually reloads the PhoneDetails View, the changeLogs$ array is empty, UNLESS I manually inject a property of the unwrapped observable like this:
<phone-history-component [phoneNumberId]="(phoneNumber$ | async).id" [phoneNumber$]="phoneNumber$"></phone-history-component>
If I just inject the phoneNumber$ like this
[phoneNumber]="(phoneNumber$ | async)"
it doesn't work. (I don't use these additional inputs in the component)
Now I know that there are other ways to implement this functionality, but I'm merely interested in why the code behaves like this?
It feels like I'm lacking some fundamental understanding of the basic rxjs pipeline. So..what is happening here exactly?
Any help is appreciated.
UPDATE
BizzyBob was kinda right. When directly reloading the component, the phoneNumber$
Observable didn't have any value when the filter
function got fist executed. I fixed this with a quick check:
map(pn => {
return !!pn[0] ? pn[1].filter(logs => logs.pkId === pn[0].id) : null;
}));
Now.. is this the recommended way to do it, or are there better ways?