PROBLEM INTRODUCTION
I have button-address child component which onInit loads a list of mapItems:
ngOnInit() {
this.refreshDataList();
}
protected refreshDataList(): void {
this.subscription = this.getDataList()
.pipe(
switchMap((result: AddressModel[]) => {
this.dataSource.data = [...result].map((d) => {
return {
address: d,
selected: this.selectedItems
? this.selectedItems.some(
(it) =>
it.address.pointName ===
d.pointName && it.selected
)
: false,
};
});
this.sortList(this.dataSource.data);
return this.preSelectUserPreferencesPOIs();
})
)
.subscribe();
}
protected getDataList(): Observable<AddressModel[]> {
return this.store.pipe(select(selectZoi));
}
The value of this.dataSource.data is set inside the switchMap() operator. This value is important because later the user will select elements from the list. So I will listen for the click events from the user, find the right element of this.dataSource.data and update the selected item.
My issue is that when the app inits, I also receive an @Input from another stream whose aim is to programatically select the appropiate item in the list of this.dataSource.data:
@Input()
set proximityReportPoiZoi(poiZoi: ProximityReportPoiZoi) {
this.toggleSelectedPoiZoi(poiZoi.id);
}
protected toggleSelectedPoiZoi(poiZoiId: string) {
const addressZoneSelectionModel = this.dataSource.data.find(
(item) => poiZoiId === item.address.id
);
const address = addressZoneSelectionModel.address;
if (addressZoneSelectionModel.selected) {
addressZoneSelectionModel.selected = false;
this.showHidePoiZoi(address, false);
} else {
addressZoneSelectionModel.selected = true;
this.showHidePoiZoi(address, true);
}
}
THE BUGGY LINE
However, because the request to the store takes some time, when the @Input (which by the way is also an observable) is received by the component, the code inside toggleSelectedPoiZoi() cannot find the appropiate item as this.dataSource.data is still empty:
const addressZoneSelectionModel = this.dataSource.data.find(
(item) => poiZoiId === item.address.id
);
THE QUESTION
How can I make my @Input() wait for the component to load the data for this.dataSource.data before executing this.toggleSelectedPoiZoi()? This issue only happens during the app init.
THINGS I HAVE TRIED
- Await for the observable to load the data
@Input()
set proximityReportPoiZoi(poiZoi: ProximityReportPoiZoi) {
const updatePoiZoiSeletion = async () => {
await this.refreshDataList().toPromise();
this.toggleSelectedPoiZoi(poiZoi.id);
}
updatePoiZoiSeletion();
}
But it never gets to execute the following line with this.toggleSelectedPoiZoi() method. If I change .toPromise() for .subscribe(), the value of this.dataSource.data is still an empty array so no item can be selected.
- ngOnChanges
However no success as although I can listen for the changes on the value of the @Input, I cannot listen for changes in this.dataSource.data.
- Get the value of the @Input() by subscribing it at a later stage in the parent component, in ngAfterViewInit() cycle.
Angular complains that because the @Input is passed through the template, the value of proximityReportPoiZoi$ property has changed after parent component initialization. See the parent template:
<app-button-address
[proximityReportPoiZoi]="(proximityReportPoiZoi$ | async)"
></app-button-address>
Any help is highly appreciated beforehand :)