Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to show a placeholder image before the actual image loads in an Ionic 2 or 3 app

Good day,

I'm working on an Ionic application and I'm loading images dynamically from a JSON feed. I would like that when the images are being pulled in from the external URL that a placeholder image shows in its place, thereafter, the placeholder image should then be replaced by the "real" image once its loaded.

An example of my current situation is:

<ion-card *ngFor="let item of items"...
 <img [src]="item.picture" />

Thanks & Regards.

like image 719
TC Roberts Avatar asked Sep 29 '17 10:09

TC Roberts


2 Answers

Most of the answers are about adding the logic of the loaded check in the same view, but it seems not appropriate. Instead, you can create your own directive that will take care of it. You can take a look at this amazing article to see how it can be done.

First copy this GIF in your src/assets folder, and name it preloader.gif.

Then add this custom directive. The code is pretty much self-explanatory:

// An image directive based on http://blog.teamtreehouse.com/learn-asynchronous-image-loading-javascript
import {Directive, Input, OnInit} from '@angular/core';

// Define the Directive meta data
@Directive({
  selector: '[img-preloader]', //E.g <img mg-img-preloader="http://some_remote_image_url"
  host: {
    '[attr.src]': 'finalImage'    //the attribute of the host element we want to update. in this case, <img 'src' />
  }
})

//Class must implement OnInit for @Input()
export class ImagePreloader implements OnInit {
  @Input('img-preloader') targetSource: string;

  downloadingImage : any; // In class holder of remote image
  finalImage: any; //property bound to our host attribute.

  // Set an input so the directive can set a default image.
  @Input() defaultImage : string = 'assets/preloader.gif';

  //ngOnInit is needed to access the @inputs() variables. these aren't available on constructor()
  ngOnInit() {
    //First set the final image to some default image while we prepare our preloader:
    this.finalImage = this.defaultImage;

    this.downloadingImage = new Image();  // create image object
    this.downloadingImage.onload = () => { //Once image is completed, console.log confirmation and switch our host attribute
      console.log('image downloaded');
      this.finalImage = this.targetSource;  //do the switch 😀
    }
    // Assign the src to that of some_remote_image_url. Since its an Image Object the
    // on assignment from this.targetSource download would start immediately in the background
    // and trigger the onload()
    this.downloadingImage.src = this.targetSource;
  }

}

Then add the new directive to your app module, like this:

import { NgModule, ErrorHandler } from '@angular/core';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { MyApp } from './app.component';
import { ImagePreloader } from '../components/img-preload/img-preload';

@NgModule({
  declarations: [
    MyApp,
    ImagePreloader, // <------- Here!
    // ...
  ],
  imports: [
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    // ...
  ],
  providers: [{provide: ErrorHandler, useClass: IonicErrorHandler}]
})
export class AppModule {}

This is how you can use your new custom directive:

<img img-preloader="https://images.unsplash.com/photo-1413781892741-08a142b23dfe" alt="">

And this is how it will look like:

Result

You can then set the height/width of the container of the image, so both the preloader gif and the final image have the same dimensions.

like image 98
sebaferreras Avatar answered Sep 17 '22 02:09

sebaferreras


As far as i know, there is no Ionic way to do it. But you still can do it by javascript and css.

CSS way:

Create a div cover your image and set the placeholder image is background-image of that div.

<div class="image">
    <img src="your_main_image"/>
</div>
.image{
    background-image: url('your_placeholder_image');
}

Javascript way:

There are several methods by javascript that you can easily find in stackoverflow so i will not re-answer here. This one is an example

like image 34
Duannx Avatar answered Sep 21 '22 02:09

Duannx