Optimus Pette Optimus Pette - 7 months ago 64
Javascript Question

Angular 2 Binding to a function on the view results to infinite calls to the data service

I'm trying to bind a

src
attribute of images inside an
ngFor
directive that looks like this:

<div *ngFor="imageId of imageIds">
<img [attr.src]="imageSrc(imageId)" alt="{{imageId}}">
</div>


the
imageSrc
method inside the component looks like this:

imageSrc(imageId: string){
var hostUrl = "http://192.168.0.101:3000/";
var imageUrl = hostUrl+"images/"+imageId;
var imgSrc = "";

this._imageService.getImage(imageId)
.subscribe(image => {
imgSrc = hostUrl + image.url
});
return imgSrc;
}


The
getImage
function in the
Injectable
ImageService
looks like this:

getImage(id: string) {
var _imageUrl = "http://192.168.0.101:3000/images/"+id;
return this.http.get(_imageUrl)
.map(res => <Image>res.json().data)
.catch(this.handleError)
}


The problem is, with only two
imageIds
the
*ngFor
directive renders the two list items as expected (but no images displayed) but the call to the data service doesn't stop, it gets the two images over and over on what appears to be an infinite loop until the application crashes. what I'm I doing wrong?

Answer

I don't think this is related to *ngFor. If you bind from the view to a function then this function is called every time Angular runs change detection which is by default on every event that happens on your page.

In devMode (in contrary to prodMode) change detection even runs twice for each event.

Store the result in a property and bind to that property instead or at least return a cached result from your function on subsequent calls if the input parameter (id:string) hasn't changed since the last call.

For example like shown in http://stackoverflow.com/a/36291681/217408