You're looking for the async pipe:
The async pipe subscribes to an Observable or Promise and returns the
latest value it has emitted. When a new value is emitted, the async
pipe marks the component to be checked for changes. When the component
gets destroyed, the async pipe unsubscribes automatically to avoid
potential memory leaks.
So, if your observable returns a string with your image src, your refactored code might look like:
..img ... src="{{getUserProfilePicture(request.clientId) | async}}" ... ">
I created a working example of the async pipe in an ngFor loop for reference.
Some potential things to watch out for with the async pipe: every time you use that same observable, it will subscribe to the observable again unless you capture the value using the as syntax. What this means is: if you have an async pipe that calls a web service, for example, it will be called multiple times if you do something like this:
<!-- Async pipe subscribes once... -->
<img src="{{someHttpCall(request.clientId) | async}}"/>
<!-- Async pipe subscribes again... -->
<p>Img loaded from: {{someHttpCall(request.clientId) | async}}</p>
If you wanted to refactor the above to us the as syntax to capture the output and avoid multiple server calls, it would look like this:
<!-- Capture our observable to prevent subsequent subscriptions.
Async pipe only subscribes once. -->
<ng-container *ngIf="someHttpCall(request.clientId) | async as imgSrc">
<img src="{{ imgSrc }}"/>
<!-- Also note we don't need the async pipe because it already subscribed
to the observable for us and we captured the value in our template -->
<p>Img loaded from: {{ imgSrc }}</p>
</ng-container>
Anyway, that's a pitfall that a lot of new Angular developers fall into so I figured I wouldn't introduce the async pipe without at least a little word of caution.
requestsis an array of observables? Or is it thatgetUserProfilePicturereturns an observable? - Dean