Hi, iam fighting a little with change detection in my Ionic app. Iam using this code on my homepage
this.udpService.sendUdpMessage(this.settings,this.lastCodeType,this.lastCode,this.entry).then(result=>{
setTimeout(()=>{
this.showStatus=false;
},5000)
});
Iam calling my updService, send message and after communication ends, i display some status(Ok, Not Ok, Error …) in special div with ngIf directive, that shows component, when showStatus is true and hide it, when its false. Problem is it doesnt actually work, i have to click some button in my app to see changes. Any idea how to fix this?
Hi,
The problem may not be with your promise/setTimeOut but rather how you’re updating the UI. Can you share that code.
Of course. but its very simple, this is the component i use for displaying status
<status-box *ngIf="showStatus" [color]="udpService.statusColor" [text]="udpService.statusText"></status-box>
and this is status box component inner html:
<ion-row>
<ion-card [style.backgroundColor]="color" class="statusCard">
<div class="cardTitle">{{ text }}</div>
</ion-card>
</ion-row>
Was worth a shot.
Take a look at this: https://stackoverflow.com/questions/11714397/settimeout-scope-issue
Check out what this
is in the different scopes.
1 Like
Most weird thing is, that i have two similar methods in my home page - one for reading nfc and one for reading barcode.
first one for barcode looks like this
readBarcode() {
this.barcodeScanner.scan().then((barcodeData) => {
let date=new Date();
this.lastCode=barcodeData.text;
this.lastCodeType="codeBC";
this.udpService.setStatus("orange", "Probíhá komunikace");
this.showStatus=true;
this.udpService.sendUdpMessage(this.settings,this.lastCodeType,this.lastCode,this.entry).then(result=>{
this.logService.AddToLog(date,this.lastCode,result);
setTimeout(()=>{
this.showStatus=false;
},5000)
});
});
}
With this one, the hiding and showing works, no problem.
Second method for nfc looks like this :
readNFC() {
let alert = this.alertCtrl.create({
title: 'Přiložte kartu:', enableBackdropDismiss: false,
buttons: [{
text: 'Zrušit',
role: 'cancel',
handler: data => {
subscription.unsubscribe();
}
}]
});
alert.present();
let subscription = this.nfc.addTagDiscoveredListener().subscribe((nfcData) => {
console.log(nfcData);
let date=new Date();
alert.dismiss();
subscription.unsubscribe();
let uid=this.transformTag(nfcData.tag.id);
this.lastCode=uid;
this.lastCodeType="codeRF";
this.udpService.setStatus("orange", "Probíhá komunikace");
this.showStatus=true;
this.udpService.sendUdpMessage(this.settings,this.lastCodeType,this.lastCode,this.entry).then(result=>{
this.logService.AddToLog(date,this.lastCode,result);
setTimeout(()=>{
this.showStatus=false;
},5000)
});
});
}
and in this case it doent work, i have to click on button to see changes. Where is the problem? Does it have something to do , that i NFC method, it is inside subscription?
let _self=this
this.udpService.sendUdpMessage(this.settings,this.lastCodeType,this.lastCode,this.entry).then(result=>{
setTimeout(()=>{
_self.showStatus=false;
},5000)
});
if doesn’t work try use ngzone
let _self=this
this.udpService.sendUdpMessage(this.settings,this.lastCodeType,this.lastCode,this.entry).then(result=>{
setTimeout(()=>{
_ngzone.run(()=>{
_self.showStatus=false;
})
},5000)
});
and don’t forgot inject ngzone into constructor
import {NgZone} from '@angular/core';
constructor(private _ngzone: NgZone) {}
console.log(this);
Once you know what this
is, you can try understand why it is what it is…
it logs correct object with showStatus variable on it. The problem is that it doesnt trigger change detection
it works like this, i dont even have to save this into another variable.
this.udpService.sendUdpMessage(this.settings,this.lastCodeType,this.lastCode,this.entry).then(result=>{
this.logService.AddToLog(date,this.lastCode,result);
setTimeout(()=>{
this.ngZone.run(()=>{
this.showStatus=false;
});
},5000)
});
but using manually change detection doesnt seems like a good practice, or iam wrong? Is there any other way?
I think it is because of the above that angular change detection fails. Not the setTimeout. And then the Zone seems to be the easiest way. Of course you could try many other ways like Event emitters, but that makes the code more complicated.
yea but why, or how do i fix it, code of this method in service looks like this :
sendUdpMessage(settings, lastCodeType, lastCode, entry){
return new Promise(resolve=>{
let arrayBuffer=this.str2ab("PdaId="+settings.pdaId+"&PdaName="+settings.pdaName+"&"+lastCodeType+"="+lastCode+"&dir="+entry);
chrome.sockets.udp.create(socketInfo=>{
chrome.sockets.udp.bind(socketInfo.socketId, '0.0.0.0', 0, (bindresult) => {
console.log(socketInfo);
var socketId = socketInfo.socketId;
chrome.sockets.udp.onReceive.addListener((info)=>{
console.log(info);
console.log(this.ab2str(info.data));
let result=this.ab2str(info.data);
if(result=="vstupPovolen"){
this.setStatus("green", "Vstup povolen");
}
else{
this.setStatus("red", "Vstup nepovolen");
}
chrome.sockets.udp.close(socketInfo);
resolve(result);
});
chrome.sockets.udp.send(socketId, arrayBuffer,settings.serverIp, 4040, function(sendInfo) {
console.log(sendInfo);
console.log("sent " + sendInfo.bytesSent);
});
setTimeout(()=>{
console.log("no answer");
this.setStatus("grey", "Chyba komunikace");
resolve("no answer");
},3000);
});
});
});
The problem is just because of the:
enableBackdropDismiss: false
In the alert.
I have the same problem.