Why Ionic doesn't update variables content?

Hi guys,
I already had a similar problem with another plugin and I didn’t find a solution.
I can’t understand what I’m doing wrong.

In this app I’m reading the sms sent to the mobile and I’m counting them in a class variable.
I’d like simply to show the value of this counter in the same page.
The problem is that, when the counter increments its value, the value on the page doesn’t change.
I have to change directly the html in this way: document.getElementById('sms_arrived').innerHTML=document.getElementById('sms_arrived').innerHTML = String(this.smsArrived).

This is the code of the function that increments the counter:

    startWatchSMS() {
        if (this.isPluginSupported) {
            SMSReceive.startWatch(
                () => {
                    this.isPluginStarted = true;
                    this.startSpinner();
                    this.smsArrived = 0;
                    document.getElementById('sms_arrived').innerHTML = String(this.smsArrived );

                    document.addEventListener('onSMSArrive', (e: any) => {
                        const IncomingSMS = e.data;
                        console.log('BEFORE:', this.smsArrived);
                        this.smsArrived += 1;
                        console.log('AFTER:', this.smsArrived);
                        document.getElementById('sms_arrived').innerHTML = String(this.smsArrived);
                        this.processSMSData(IncomingSMS);
                    });
                },
                (err) => {
                    console.log('watch start failed', err);
                    this.isPluginStarted = false;
                    this.errorsReceivingSMS += 1;
                    this.stopSpinner();
                }
            );
        }
    }

The log messages show the right data, that is the counter is updated correctly.
This is the page that shows the counters:

    <div class="test_messages">
        <ion-list>
            <ion-item>
                <ion-label color="success">Number of SMS received (method1):</ion-label>{{ smsArrived }}
            </ion-item>
            <ion-item>
                <ion-label color="success">Number of SMS received (method2):</ion-label>
                <ion-input type="text" [ngModel]="smsArrived"></ion-input>
            </ion-item>
        </ion-list>
        <div class="msg_block">Number of SMS received (method3):</div>
        <div class="msg_block" id="sms_arrived">0</div>
    </div>

The problem is that only the method3 show the right value of the variable.
The other two methods show 0 until I stop the plugin.
These are the screenshots:

But, if I stop the plugin, the right value of the variable is shown everywhere:

Why the variables are not updated?
And why if I act directly on the Dom of the page it works?

I’ve published the code I’m using here.

Thank you very much

cld

This is more or less the entire reason the ionic-native project exists, so whenever you are dealing with native plugins,

  • choose one with an existing ionic-native shim
  • write an ionic-native shim for it
  • keep reading

What ionic-native does under the hood is convert callback conventions to Promises, which has the beneficial side effect of getting stuff running in the right zone. The way you are interacting with this plugin goes behind Angular’s back, which is why Angular can no longer do its job. While there are much cleaner ways of fixing this than I’m going to describe here (namely, effectively writing your own ionic-native shim and submitting a PR to get it included in ionic-native proper), here is a way to do this manually:

export interface SMSMessage {
  address: string;
  body: string;
  // maybe more stuff goes here, left as an exercise for the reader
}

export interface SMSEvent {
  data: SMSMessage;
}

declare var SMSReceive: any; // i h8 this

@Injectable()
class SMSReceiver {
  private incoming$ = new Subject<SMSMessage>();

  constructor(plat: Platform) {
    plat.ready().then(() => {
      if (typeof(SMSReceive) !== "undefined") {
        SMSReceive.startWatch(() => {
          document.addEventListener("onSMSArrive", (evt: SMSEvent) => {
            this.incoming$.next(evt.data);
          });
        });
      }
    });
  }

  watch(): Observable<SMSMessage> {
    return this.incoming$;
  }
}

It wouldn’t be too hard to modify this to allow starting and stopping from app control, but I wanted to focus on the core issue. Your client code can simply:

class Page {
  constructor(private smser: SMSReceiver) {
    this.smser.watch().subscribe((sms) => {
      // happy happy joy joy we're in Angular's zone and change detection will work as expected
    });
  }
}
1 Like

Thank you for your tutorial, I’m reading it and studying it carefully.
I didn’t know these things about Ionic Native.
thank you very much

cld