Mujibur Rahman
Mujibur Rahman

Reputation: 461

How to load image with spinner in Angular2

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

Answers (4)

Sephen
Sephen

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

perezperret
perezperret

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

null canvas
null canvas

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

Peter Schuhknecht
Peter Schuhknecht

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

Related Questions