Reputation: 461
My app has many images with descriptions. When user navigates, the text appears first and the image loads with some delay. I would like to add a spinner here. A directive which shows spinner while loading the image and shows image like:
<myimgdir [src]='myimage.png'></myimgdir>
How to add the spinner, track image loading, and display it accordingly?
Upvotes: 18
Views: 35381
Reputation: 1111
I think the easiest way is to use onError
event on the img
element:
<img [src]="image.src" onError="this.src='assets/my/fancy/loader.gif';">
Upvotes: 2
Reputation: 366
In your controller, add a function to handle the onLoad
event, setting the state to {loading: false}
:
loading: boolean = true
onLoad() {
this.loading = false;
}
In your template, render a loading GIF (or whatever you want) while the state is loading === true
. The tricky part is that you should just hide the img
element with [hidden]="true/false"
as opposed to prevent it from rendering so it will actually load the src
, then just bind the onLoad
function in your controller to the (load)
event on the actual image:
<img *ngIf="loading" src="/assets/loading.gif" alt="loading" />
<img [hidden]="loading" (load)="onLoad()" src="{{ source }}" />
This solution is functionally the same as AngJobs's, but it's more declarative and a little less cumbersome IMO.
PS: Using [hidden]="boolean"
instead of *ngIf
is a bit of a gotcha, you should look here to understand why and for a solution on how to apply it safely.
Upvotes: 33
Reputation: 10613
The idea is to display the spinner by default. Create a separate Image
object that would be displayed when loading is complete.
var img = new Image();
/// set handler and url
img.onload = onloadHandler;
img.src = imageURLs[i];
/// if image is cached IE (surprise!) may not trigger onload
if (img.complete) onloadHandler().bind(img);
Upvotes: 1
Reputation: 185
You don't need a function here, just add the following to your component:
imageLoader = true;
In template, add the following:
<div [hidden]="!imageLoader">Loading...</div>
<img [hidden]="imageLoader" src=".../image.png" (load)="this.imageLoader = false;" />
As you see, there is text instead of a GIF because actually an animation GIF also must be loaded. In some cases, this could take much more time than loading the image itself.
If the GIF is loaded already, you can use:
<img [hidden]="!imageLoader" src=".../loading_spinner.gif" />
<img [hidden]="imageLoader" src=".../image.png" (load)="this.imageLoader = false;" />
Upvotes: 11