How to show placeholder image before loading actual image in Ionic 2 or 3 app

Good afternoon,

I am working on an ionic application and I am loading images dynamically from the JSON channel. I would like to refer to the external URL, which the image appears on it in place, after which the placeholder image is then replaced with a "real" image after loading it.

An example of my current situation:

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

Thanks and respect.

+5
source share
5 answers

Can you change your JSON to have a loaded boolean property? If possible, do this:

 <ion-card *ngFor="let item of items"> <img [src]="item.picture" (load)="item.loaded = true" [hidden]="!item.loaded" /> <img src="../path/to/your/placeholer/image.jpg" [hidden]="item.loaded"> </ion-card> 

You will have a loaded property, which is always initialized to false , when the image loads an event (load) , it will fire and change the property of the loaded image to true, hide the placeholder image and display the loaded image.

If you cannot change this JSON (or if it is too large for editing), you can use the above code, but on the .ts page

follow these steps:
 public functionWhoseIsLoadingYourJson(){ // HTTP REQUEST FOR JSON .subscribe(response => { response.forEach(element => { element.loaded = false; }); this.items = response; }); } 

Just repeat your answer, and in each object set the loaded property to false. If this leads to some error, you can put your <ion-card> inside the div using * ngIf

 <div *ngIf="this.items != null"> <!-- ion card --> </div> 

EDIT - JSON Update

Since Firebase has three options for updating your JSON. The first one is a function that you would execute once to update your database, and the second is the code that I gave (iterating through the results and pressing a boolean value), but it will be different, since you use Firebase.

First decision:

Somewhere in your code, it could be any page, you just need to execute it once:

 firebase.database().ref('myDataNode').on('value', snapshot => { for(let key in snapshot.val()){ firebase.database().ref('myDataNode/' + key + '/loaded').set(false); } }); 

See that I myDataNode over all the options in myDataNode and use their key to set the loaded property to false . But be careful when using set , since you can override all your nodes before doing this method, remember that you are exporting a Firebase node to have a backup. And if you click your images on Firebase from anywhere in your code, remember to change it to set the loaded property together.

The second, as already mentioned, is what I did in this answer, but now I use it inside your Firebase call and using the forEach method that comes with the snapshot:

 firebase.database().ref('myDataNode').on('value', snapshot => { snapshot.forEach(element =>{ this.myDataNode.push({ picture: element.val(), // maybe it needs to be element.val().nameOfYourProperty loaded: false }) }); }); 

This will add a new element to your array with the image URL and property loaded. If it cannot recognize the .push() method, just declare your variable printed as an array:

 public myDataNode: any[]; 

The third one is simply updated locally, repeated through a firebase snapshot, saves the result in a local variable, creates a new property and inserts it into your array:

 firebase.database().ref('myDataNode').on('value', snapshot => { for (let key in snapshot.val()){ snapshot.forEach(item => { // iterate snapshot let record = item.val(); // save the snapshot item value in a local variable record.loaded = true; // add the property this.newArray.push(record); // push it to your array that'll be used in ng-for return true; // return true to foreach }); } }); 

Hope this helps.

0
source

Most of the answers are about adding the logic of the loaded check in the same way, but this does not work. Instead, you can create your own directive that takes care of this. You can take a look at this amazing article to find out how to do this.

The first copy of this GIF is 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]', //Eg <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 a new directive to your application module, for example:

 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 {} 

Here's 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:

Result

Then you can set the height / width of the image container, so that both the preloader gif and the final image are the same size.

+2
source

Hope you can try as below. You can save the splash screen image in the assets/images folder.

.html

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

.ts

 export class MyPage{ myImgUrl:stirng='./assets/images/myimage.png; constructor(){} } 
0
source

As far as I know, there is no ionic way to do this. But you can still do this with javascript and css.

CSS way:

Create a div cover for your image and set the background-image placeholder background-image this div.

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

Javascript Method:

There are several javascript methods that you can easily find on stackoverflow, so I will not answer again here. This example is an example.

0
source

Try the following:

.ts

 export class MyPage { placeHolder:string = './assets/img/placeholder.png'; constructor(){} } 

.html

  <img [src]=item.image ? item.image : placeHolder> 
-1
source

Source: https://habr.com/ru/post/1272217/


All Articles