Ionic2 view is not updating + Video - html

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);
});
}

Related

How to implement a lazy loading on Ion-card

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>

Color from cards are not changing after event is fired

So I've a problem where I want to change colors from my cards everytime a customer get subscribed to a gym class. ( Red for already subscribed, yellow when is open to subscription)
The problem I'm getting is, anytime when I make a subscription to one class, all the elements from the array, got the color red, instead of one.
So I've an array of classes(named fechaClases) which looks like this:
My HTML code looks like this:
<ion-card color="light" *ngFor="let fecha of fechaCards">
<ion-item color="warning">
<ion-icon slot="start" name="fitness"></ion-icon>
<ion-label>
<h2 style="font-weight: bold">{{ fecha | date:'d/MMMM/yyyy' | uppercase }}</h2>
</ion-label>
</ion-item>
<!-- CONTENIDO --> ---> **Here is where I want to change colors**
<ion-card-content>
<ng-container *ngFor="let clase of fechaClases">
<ion-item [color]="getColor()" (click)="inscripcion(clase)" *ngIf="clase.horaCierre == fecha">
<h2 slot="start" style="font-weight: bold">{{ clase.horaApertura | date: 'shortTime' }}</h2>
<h2 slot="end">{{ "Cupos disponibles" + " " + clase.cuposDisponibles + "/" + clase.cupos }}</h2>
</ion-item>
</ng-container>
</ion-card-content>
</ion-card>
getColor()
for (let index = 0; index < this.fechaClases.length; index++) {
if (this.fechaClases[index].estaInscripto == true) {
console.log(this.fechaClases[index].estaInscripto, 'true');
return 'danger'
}
else {
return 'warning'
}
}
what i'm doing wrong? Hope anyone can help me :) Thanks in advance guys!
You should think in a more "angular" way.
Your list is created by iterating over your fechaClases array, using the *ngFor directive. You just need a conditional binding of the color property, checking the estaInscripto property of each array object.
So, change this line:
<ion-item [color]="getColor()" (click)="inscripcion(clase)" *ngIf="clase.horaCierre == fecha">
with this one:
<ion-item [color]="clase.estaInscripto? 'danger' : 'warning'" (click)="inscripcion(clase)" *ngIf="clase.horaCierre == fecha">
Also, delete your getColor() function, there is no need for it.
Check this stackblitz (inside the home page .html and .ts files) with simplified, working example of the above.
https://stackblitz.com/edit/ionic-e7pfdz

How to display a array elements in HTML(ionic 3)

I'm new to ionic. Actually, I'm trying to display products added to cart in cart page. I got value from Foreach method, but when I try to display, it won't show.
cartpage(){
this.cart.cartview().then((result) => {
this.cartdisplay = JSON.parse(JSON.stringify(result));
this.categorydata = JSON.parse(JSON.stringify(this.cartdisplay.data));
console.log('result11:'+JSON.stringify(this.categorydata));
var arr = Object.keys(this.categorydata.items);
//this.cartarray =[];
arr.forEach( a =>{
this.cartarray['orderitem_name']= this.categorydata.items[a].orderitem_name;
this.cartarray['orderitem_quantity']= this.categorydata.items[a].orderitem_quantity;
console.log('cart : '+this.cartarray['orderitem_quantity']);
console.log(a) //item id
console.log(this.categorydata.items[a].cart_id) //product id
})
console.log(this.cartarray);
})
}
in the console log, orderitem_name and orderitem_quantity is displaying, but it does not show in the HTML page.
This is my HTML code:
<ion-card>
<ion-card-header>Items</ion-card-header>
<!--<ion-card-content >Your cart is empty!</ion-card-content>-->
<ion-list no-lines>
<ion-item *ngFor="let tms of cartarray;" >
<ion-avatar item-left>
<img src="">
</ion-avatar>
<h2><b>{{tms.orderitem_name}} x {{tms.orderitem_quantity}}</b></h2>
<div [ngSwitch]="product?.price_discount">
<p *ngSwitchCase="true">₹ <span st></span> <span></span></p>
<p *ngSwitchDefault>₹ <span style="text-decoration: line-through;"></span> <span></span></p>
</div>
<div>
<button primary large>
<ion-icon name="add" (click)="increaseQuantity(i)"></ion-icon>
</button>
<button primary large>
<ion-icon name="remove" (click)="decreaseQuantity(i)"></ion-icon>
</button>
</div>
</ion-item>
</ion-list>
<!--<ion-card-content ><div>Total for this order is ₹ </div></ion-card-content>-->
</ion-card>
Help me to display a value in foreach loop in ionic 3
You can try these
this.cart.cartview().then((result) => {
this.cartarray = Object.keys(result["data"]["items"]).map((key) => {
return result["data"]["items"][key];
});
})
And your html file
<div *ngFor="let tms of cartarray;">
<h2><b>{{tms.orderitem_name}} x {{tms.orderitem_quantity}}</b></h2>
</div>
i don't no ionic so thats why i'am testing with div but it's work fine.
you miss the "tms" variable name before display list of data
<ion-item *ngFor="let tms of cartarray;" >
<h2><b>{{tms.orderitem_name}} x {{tms.orderitem_quantity}}</b></h2>
</ion-item>
You should debug your array like
<ion-item *ngFor="let tms of cartarray;" >
<h2><b>{{tms | json }} x {{tms | json}}</b></h2>
</ion-item>
Thanks

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);
});

How to write if/else in ionic html page?

I made an Ionic WordPress app that gives me an error every time a post is published without a featured photo.
What I'm trying to do is filter out those posts that doesn't have a photo but I don't know how to use if/else condition in Ionic.
This is the code for home.html
<ion-card *ngFor="let item of items">
<img src="{{item._embedded['wp:featuredmedia'][0].media_details.sizes.thumbnail.source_url}}"/>
<ion-card-content>
...
</ion-card-content>
</ion-card>
If you're trying to remove items from items that don't have a thumbnail, it's better to do it on the backend when you get them.
this.items = this.items.filter(function(item) {
return (item &&
item._embedded &&
item._embedded['wp:featuredmedia'] &&
item._embedded['wp:featuredmedia'][0] &&
item._embedded['wp:featuredmedia'][0].media_details &&
item._embedded['wp:featuredmedia'][0].media_details.sizes &&
item._embedded['wp:featuredmedia'][0].media_details.sizes.thumbnail &&
item._embedded['wp:featuredmedia'][0].media_details.sizes.thumbnail.source_url);
});
If you want to get every item, thumbnail or no, but hide the thumbnail if it doesn't exist, use *ngIf on your img tag.
<ion-card *ngFor="let item of items">
<img *ngIf="item &&
item._embedded &&
item._embedded['wp:featuredmedia'] &&
item._embedded['wp:featuredmedia'][0] &&
item._embedded['wp:featuredmedia'][0].media_details &&
item._embedded['wp:featuredmedia'][0].media_details.sizes &&
item._embedded['wp:featuredmedia'][0].media_details.sizes.thumbnail &&
item._embedded['wp:featuredmedia'][0].media_details.sizes.thumbnail.source_url"
src="{{item._embedded['wp:featuredmedia'][0].media_details.sizes.thumbnail.source_url}}"/>
</ion-card>
Note: The reason you should check each layer of the object is because if any one of them is missing, you'll get a TypeError saying "could not find property X of undefined".