How to implement a lazy loading on Ion-card - html

So im using ionic with the firebase data and i have to load a lot of it.
And because of this massive data to load, not all images appear (As you can see on the screen shot).
So... what should i do and is it possible to lazy load the cards with the data.
there is my code
<div *ngIf="postcall1">
<ion-card (swipeleft)="goTochat(postscall1)" *ngFor="let postscall1 of postcall1">
<img class="pP" src="https://ucarecdn.com/{{ postscall1.profilePic }}/-/scale_crop/200x200/center/" />
<ion-img (press)="openOptionSheet(postcall1)" (click)="open(postscall1)"
src="https://ucarecdn.com/{{postscall1.postboost1ID}}/-/preview/{{postscall1.effect}}"></ion-img>
<ion-button mode="ios" class="this-button" color="light" fill="clear">
<ion-icon slot="icon-only" [name]="heartType"></ion-icon>
</ion-button>
</ion-card>
</div>
and i have these 3 firebase function to load
ngOnInit() {
const postcall = this.aff.httpsCallable('postscall')
this.sub = postcall({}).subscribe(data => {
this.postcall = data
console.log("postcall");
console.log(this.postcall);
})
///
const postcall1 = this.aff.httpsCallable('postscall1')
this.sub = postcall1({}).subscribe(data => {
this.postcall1 = data
console.log("postcall1");
console.log(this.postcall1);
})
}
thank you in advance

As you are using Ionic, put your items in an Ion virtual scroll.
In the documentation, it is clearly explained that only the necessary elements will be loaded.
For performance reasons, not every record in the list is rendered at once; instead a small subset of records (enough to fill the viewport) are rendered and reused as the user scrolls.
Not tested code below, but this example might help you.
<ion-virtual-scroll [items]="postcall1">
<ion-card *virtualItem="let postscall1">
<img class="pP" src="https://ucarecdn.com/{{ postscall1.profilePic }}/-/scale_crop/200x200/center/" />
<ion-img (press)="openOptionSheet(postcall1)" (click)="open(postscall1)"
src="https://ucarecdn.com/{{postscall1.postboost1ID}}/-/preview/{{postscall1.effect}}"></ion-img>
<ion-button mode="ios" class="this-button" color="light" fill="clear">
<ion-icon slot="icon-only" [name]="heartType"></ion-icon>
</ion-button>
</ion-card>
</ion-virtual-scroll>

Related

How to remove the image element from DOM when 403 error occurs in Angular

Is there a way I can remove the entire image element from DOM when 403 error occurs to that image while fetching it from the API so that the title of the card is expanded to the whole width of the card.
This is what I tried so far
HTML
<div *ngFor="let item of items">
<ion-row>
<ion-col>
<div>{{ item.title }}</div>
</ion-col>
<ion-col size="4" class="ion-text-center">
<img src="{{ item.imageurl }}" (error)="handleImageError($event)" />
</ion-col>
</ion-row>
</div>
TS
handleImageError(e) {
e.target.style.display = 'none';
}
I have created a working example using StackBlitz. Could anyone please help.
You are looking for *ngIf on image container, as it removes / adds the element from the DOM. And you will also have to slightly modify the handleImageError.
StackBlitz
<div *ngFor="let item of items">
<ion-row>
<ion-col>
<div>{{ item.title }}</div>
</ion-col>
<ion-col *ngIf="!item.hide" size="4" class="ion-text-center">
<img [src]="item.imageurl" (error)="handleImageError(item)" />
</ion-col>
</ion-row>
</div>
And then in the script, in the handleImageError - do this:
items = [
{imageUrl: '5353ssa.png'},
{imageUrl: 'https://latam.kaspersky.com/content/es-mx/images/product-icon-KSOS.png'},
{imageUrl: '5353ssa.png'},
{imageUrl: '5353ssa.png'},
]
handleImageError(image) {
image.hide = true;
}
Your problem is about your container. U have two columns. Then u will hide column instead of image. U can use ngIf
https://stackblitz.com/edit/ionic-a5wy8u
<ion-col *ngIf="!car.isSHOW">
<ion-card-content>
<img src="{{car.url}}" (error)="handleImageError(car)">
</ion-card-content>
</ion-col>
in component change its to true
handleImageError(e) {
e.isSHOW = true;
}
I would suggest you to use ngIf to hide the complete image, the way I would have address this is
Create a boolean variable at the top of your component.
let shouldHide = false;
Use this variable and ngIf at your image, you can use this at the container level or the image level itself like.
<img src="{{ imageurl }}" (error)="handleImageError($event)" *ngIf="shoudHide"/>
Assign true in case of error
handleImageError(e) {
e.target.style.display = 'none';
this.shouldHide = true;
}
Hope it helps

scroll to bottom not working chatwindow ionic

I have a chat page in my app where the chat-div is inside a wrapper-div. The structure looks like this:
<ion-content>
<div class="wrapper>
<div class="chatwindow">
<ion-grid>
<ion-row *ngFor="let message of messages">
<ion-col *ngIf="message.fromId !== myUid>
<div class="message other-message>
<span>{{message.text}}</span>
</div>
</ion-col>
<ion-col *ngIf="message.fromId === myUid>
<div class="message my-message>
<span>{{message.text}}</span>
</div>
</ion-col>
</ion-row>
</ion-grid>
</div>
</div
</ion-content>
My problem is that I am not able to make the chatpage scroll to bottom (both at pageload and when new messages arrives).
What I have tried so far:
TS: file
import {IonContent} from '#ionic/angular';
#ViewChild(‘content’) content: IonContent;
ngOninit(){
setTimeout(()=>{this.content.scrollToBottom();},200);
}
HTML file:
<ion-content #content>
Above does not give any effect, i also tried using ngZone and [scrollEvents=“true”].
The only thing that has given some effect is [ScrollTop]=“content.scrollheight”. But then the whole chatpage reloades everytime a message arrives and it scroll up and down very fast.
Any help with this will be much appreciated.
Thank you in advance.

Ionic 4 dynamic photo url isn't working - no image shown

In my app I'm doing this:
<ion-col *ngFor ="let place of intentList, let photo of photoList">
<ion-card>
<ion-card-content>
<img class="img" src = "{{photo}}" (click)="clickedImage(place.intent)">
<div>{{place.val}}</div>
</ion-card-content>
</ion-card>
</ion-col>
the array photoList contains strings with different photo url. This is the array:
this.photoList = ["./assets/images/001-breakfast.png", "./assets/images/002-brunch.png", "./assets/images/003-sandwich.png",
"./assets/images/004-food.png", "./assets/images/005-dinner.png", "./assets/images/006-cake.png", "./assets/images/007-cocktail.png"]
But this is what my app looks like:
<ion-col *ngFor ="let place of intentList; let i=index;">
<ion-card>
<ion-card-content>
<img class="img" src = "{{photo[i]}}" (click)="clickedImage(place.intent)">
<div>{{place.val}}</div>
</ion-card-content>
</ion-card>
</ion-col>
You can achieve it Using index:
This is because you can't run 2 loops in angular. So you are actually not getting the value of photo path in your variable photo.
But instead you are getting the value of variable place in the variable photo.
you can check it printing the value of photo
{{photo}}

Data in list is not binding to HTML but showing the list on console in Ionic

My data suddenly stopped binding to UI while it is displayed on console correctly
here is my code
this is my html file
<ion-content>
<ion-card *ngFor="let product of selectedproducts; let i = index">
<ion-item class="bigclass" *ngIf="length>0"><p>{{product.image}}</p>
<ion-thumbnail item-start>
<img-loader [src]="product.image" useImg></img-loader>
</ion-thumbnail>
<h4 top text-wrap>{{product.name}}</h4>
<p>Rs.{{product.price*product.quantity}}</p>
<button class="dec" (click)="decrement(product)"
[disabled]="product.disabled"><ion-icon icon-only
name="remove-circle">
</ion-icon></button>
Quantity:{{product.qtyy}}
<button class="inc" (click)="increment(product)"
[disabled]="product.disabled" ><ion-icon icon-only
name="add-circle" ></ion-icon></button>
</ion-item>
The loop is working fine and it is showing other static elements correctly but not the ones that are binded.
This is my .ts file
constructor(private storage: Storage,public navCtrl: NavController) {
this.storage.get('listforcartproducts').then((val) => {
this.selectedproducts =val;
console.log(this.selectedproducts);
});

Ionic2 view is not updating + Video

i have the following problem, my View isnt updating like it should be. If a player did his move the triggers work (i did a console log on every update of the current game [1]), but the View isnt updating regulary. So i tried to investigate this issue and added in Game.html [2] in the footer a Random number that should be updated every second [3] tocheck if the View is updating correctly. But it didnt, so i console logged every time the random value should change that worked..
My whole Gamelogic is working, if i click on a not valid Tile nothing happens, if i hit on a valid Tile Firebase is updating and sometimes both Players views are aswell.. Some times one view updates, sometimes none updates Video of this issue:
You should take a look at the footer and on that both players should have the same view of the game (besides who's turn it is and the random footer number)
https://youtu.be/Wa-P4tXh6Oo
Grey Field == Valid Field to click on
[1] Checking for Updates
checkForUpdate(key): void {
const query = firebase.database().ref("/games").child(key);
query.on('value', snap => {
console.log("update");
if (!snap.val()) return;
this.updateTurn(snap.val().turn);
this.updatewon_Fields(snap.val().won_fields);
this.updateFields(snap.val().fields);
this.updateNextField(snap.val().nextField);
});
}
I use this Game.html for Singleplayer (vs Bot), Multiplayer (2 Players on one Device) and for Multiplayer (Online). The issue just happens in the Online Multiplayer. Even tho the Data comming in is correct its not updating the view like it should
[2]
Game.html
<ion-content padding>
<ion-grid [ngClass]="getPlayerTurnClass()">
<ion-row *ngFor="let tetrisIndex of index; let r = index; trackBy: trackByFn">
<ion-col *ngFor="let x of tetrisIndex; let x = index; trackBy: trackByFn" [ngClass]="getClassValue(x)">
<div [ngClass]="{'player1_won':gameStatus.won_fields[x]==1,'player2_won':gameStatus.won_fields[x]==2,'bordern':x%2==0,'bordernplus1':x%2!=0}">
<ion-row class="ctr fc tile" *ngFor="let y of index2; let y = index; trackBy: trackByFn">
<ion-col *ngFor="let z of index2; let z = index; trackBy: trackByFn" (click)="playerClick(x,y,z)">
<div class="tile fc">
<span class="ctr tile-text" [ngClass]="{'player1':gameStatus.fields[x][y][z]==1,'player2': gameStatus.fields[x][y][z]==2}">{{(gameStatus.fields[x][y][z]==0)? ' ': ((gameStatus.fields[x][y][z]==1)? 'x' : 'o')}}</span>
</div>
</ion-col>
</ion-row>
</div>
</ion-col>
</ion-row>
</ion-grid>
<div *ngIf="gameService.isGameOver()">
<br>
<button ion-button (click)="btnRestartGame()" full block>Restart Game</button>
<button ion-button (click)="btnReturn()" full block>Return</button>
</div>
<div *ngIf="!gameService.isGameOver()&&gameStatus.gameType&&gameStatus.symbol==gameStatus.turn" class="ctr tile-text"><br><strong>Your turn!</strong><br></div>
<div *ngIf="!gameService.isGameOver()&&gameStatus.gameType!=2" class="ctr tile-text" [ngClass]="{'player1': gameStatus.turn,'player2': !gameStatus.turn}"><br><strong>{{gameStatus.turn? gameStatus.players[0].name : gameStatus.players[1].name}}'s turn!</strong><br></div>
<ion-footer>
<ion-toolbar>
<ion-title>Footer{{gameStatus.random}}</ion-title>
</ion-toolbar>
</ion-footer>
</ion-content>
[3]Gamestatus
setInterval(() => {
this.random = Math.random();
}, 500);
I already tried to add v in Game.ts
setTimeout(() => {
this._applicationRef.tick();
}, 200);
Sorry for my bad english, i hope my question was somewhat clear.Have a great weekend!
In order for something to trigger change detection it needs to be executed
within Angular’s zone.
Try this-
import { NgZone } from '#angular/core';
constructor(public zone: NgZone) {
this.zone.run(() => {
this.updateTurn(snap.val().turn);
this.updatewon_Fields(snap.val().won_fields);
this.updateFields(snap.val().fields);
this.updateNextField(snap.val().nextField);
});
}