1

Angular 5.2.0 and TypeScript 2.6.2.

I'm using the following plugin to read NFC tags. The listener starts when user presses button.

<button (tap)="doStartNdefListener()" text="Get NFC"></button>
<Label [text]="nfcText" textWrap="true"></Label>

The problem - even though the callback in doStartNdefListener() successfully scans for tag, saves the output in nfcText, outputs values from within callback, even though the value for nfcText has been changed, it does not update the UI.

import { Component } from "@angular/core";
import { Nfc, NfcTagData, NfcNdefData } from "nativescript-nfc";

export class StartComponent { 
public nfc: Nfc;
public nfcText: string;

constructor(){
    this.nfc = new Nfc();
}

public doStartNdefListener() {
    this.nfc.setOnNdefDiscoveredListener((data: NfcNdefData) => {
        if (data.message) {
            let tagMessages = [];
                data.message.forEach(record => { 
                    tagMessages.push(record.payloadAsString); });

                console.log(tagMessages.join(", "));
                this.nfcText = tagMessages.join(", ");
                console.log(this.nfcText);
            }
        },
        { stopAfterFirstRead: true, scanHint: "Scan the tag!" })
        .then(() => this.nfcText = "Listening for tag")
        .catch(err => alert(err));
    }
}

Both console outputs print out the scanned NFC tag value, but the label does not get updated.

Edit:

What is interesting is that UI updates after I execute another function after I've ran doStartNdefListener() function.

OverflowStack
  • 825
  • 1
  • 14
  • 30

3 Answers3

3

@rgantla, the problem is that Angular don´t take acount the change (don't refresh the labels). So, make a function

private changeNfcText (message:string) {
            this.ngZone.run(()=>{
              this.nfcText = message;
             });
        }
    }

Then,

this.nfc.setOnNdefDiscoveredListener((data: NfcNdefData) => {
        if (data.message) {
            let tagMessages = [];
                data.message.forEach(record => { 
                    tagMessages.push(record.payloadAsString); });

                console.log(tagMessages.join(", "));
                this.changeNfcText(tagMessages.join(", ")); //<--call the function
                console.log(this.nfcText);
            }
        },
        { stopAfterFirstRead: true, scanHint: "Scan the tag!" })
        .then(() => this.changeNfcText("Listening for tag")) //<--call the function
        .catch(err => alert(err));
    }
Eliseo
  • 50,109
  • 4
  • 29
  • 67
  • This is correct answer. The correct NfcText function is the following: private changeNfcText(message: string) { this.ngZone.run(() => { this.nfcText = message; }) } – OverflowStack Jan 29 '18 at 09:32
  • I've update the answer with your correction, thanks! – Eliseo Jan 29 '18 at 09:42
0

Have you tried the below approach?

<Label> {{nfcText}} </Label>

I cannot recall if there exists a text property on the label that you can bind to, but surely, you can use string interpolation to output your text to the view.

rgantla
  • 1,926
  • 10
  • 16
  • It's looks like a similar problem described in https://stackoverflow.com/questions/47629987/changes-dont-propagate-through-the-component – Eliseo Jan 28 '18 at 23:22
  • @Eliseo, but, in his question he mentioned that he is able to console.log(this.nfcText). So, i'm not really sure if the "this" keyword has to be bound and is out of scope of this particular class – rgantla Jan 28 '18 at 23:32
-1

Try wrapping that into a $timeout block.

$timeout(()=> {
     this.nfcText = tagMessages.join(", ");
}, 100);

This will force a digest cycle that will make your UI notice the change.

Pedro Vaz
  • 820
  • 5
  • 11