Note I have created a simplified version of this question at Template binding with function return Observable and async pipe
Template:
<div *ngIf="entity?.ext.insuredDetails.insuredType$() | async as insuredType">
{{insuredType}}
</div>
insuredType$
definition:
@NeedsElement(sp(115621),ap(116215))
insuredType$(): Observable<string> {
return empty();
}
NeedsElement
decorator:
export function NeedsElement(...mappings: NeedsElementMapping[]) {
if (mappings.length === 0) {
throw new Error('needs mapping expected');
}
let lookup = new Map<ProductId, number>();
mappings.forEach((mapping) => {
lookup.set(mapping.productId, mapping.elementId);
});
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
descriptor.value = function (...args: any[]) {
Logger.info("bbbbb");
let entity = UcEntityStoreContext.currentEntity;
let productId = entity['productId'];
if (!productId) {
throw new Error(`Cannot get product Id from host entity: ${entity.ucId}`);
}
let elementId: number = lookup.get(entity['productId']);
if (!elementId) {
throw new Error(`Cannot locate needs element ID by productId ${productId}`);
};
let enitityStore = UcEntityStoreContext.current;
let entityApi = enitityStore.apiService as QuotePolicyApiBase<any>;
let needsDefApi = NeedsDefinitionApi.instance;
return needsDefApi.fetchOne(productId, elementId).pipe(
concatMap(
nd => {
return entityApi.fetchNeedsElementValue(entity.ucId, elementId).pipe(
concatMap(needsVal => {
if (!needsVal) {
return of("");
}
if (nd.lookupId) {
return LookupApi.instance.getByPrimaryValueId(nd.lookupId, needsVal).pipe(
map(res => res.primaryValue)
);
} else {
return of(needsVal);
}
})
)
}
)
);
};
};
}
The problem is the the decorator is called multiple times:
And if it goes this branch:
then it keep sending requests to the backend servcie and the binding never output anything:
It looks like it will always keep trying evaluate the observable without ending if it is an async obserable, say this one:
Updates 14/May/2020
I got the answer from Template binding with function return Observable and async pipe
In the end I changed the Method Decorator to Property Decorator and issue fixed.