5

I'm stuck trying to access a binding from within a success function. This is the code as I have it:

import {Page, Platform, Modal, NavController, NavParams, ViewController} from 'ionic-angular';
import {Component, Input} from 'angular2/core';

@Page({
  templateUrl: 'build/pages/addModal/addModal.html',
  directives: []
})

export class addModal {
  public barcode: String = '';

  static get parameters() {
    return [[ViewController], [Platform]];
  }

  constructor(public _viewCtrl: ViewController, _platform: Platform){
    var category = "Grocery";
    this.barcode = '';

    _platform.ready().then(() => {

      this.openScanner();

    });
  }

  openScanner() {
    cordova.plugins.barcodeScanner.scan(
        (result) => {
          console.log('DEBUG || Barcode scanned: ' + result.text);
          this.barcode = result.text;
        }, 
        (error) => {
            alert("Scanning failed: " + error);
        }
      );
  }

  close() {
    this._viewCtrl.dismiss();
  }
}

When the scanner has scanned it should be updating the variable 'barcode' to the barcode scanned. I know the scanner is working because it logs the output successfully.

The issue is the DOM isn't updating at all. The HTML template is:

    <ion-item>
      <ion-label fixed>Barcode</ion-label>
      <ion-input type="text" placeholder="eg. 5058937528594" [value]="barcode" (input)="barcode=$event.target.value"></ion-input>
      <button (click)="openScanner()" outline item-right>
        <ion-icon name="qr-scanner"></ion-icon>
      </button>
    </ion-item>

I have also tried using:

<ion-input type="text" placeholder="eg. 5058937528594" [value]="barcode"></ion-input>

<ion-input type="text" placeholder="eg. 5058937528594" [(ngmodel)]="barcode"></ion-input>

<ion-input type="text" placeholder="eg. 5058937528594" #barcode></ion-input>

Also tried to wrap in a timeout function as some people have said that it could be an Angular bug. So tried:

setTimeout(() => this.barcode = result.text, 1);

Without any success. There is no error message displayed and I believe that from debugging in safari dev console that "this" is referenced correctly and accessible (using a device not in the browser. I know cordova doesn't work on a PC browser!).

Edit: So after calling console.log(this.barcode); immediately after this.barcode = result.text; I've found out that it's not updating the variable? Why would this be?

Edit 2: So now it is updating. It doesn't update if I wrap it in a timeout function so I'm guessing that it's not updating the original variable from within the success function?

Alex Bailey
  • 1,260
  • 12
  • 27

2 Answers2

11

Ensure the assignment runs in Angulars zone:

import {Component, Input} from 'angular2/core';

...

constructor(public _viewCtrl: ViewController, _platform: Platform, private zone:NgZone){ ... }

...
this.zone.run(() => this.barcode = result.text;);

See also

Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • I'm using this technique, but I can't help but asking if Angular does this automatically why do I need to do this? I mean half of the places it's working and half of the places it's not. Shall I wrap every assignment that needs to be reflected in view with this piece of code? – EralpB Nov 21 '16 at 22:37
  • 1
    Angular uses zone.js to patch async calls like `setTimeout` and `addEventListener` to know when "something" happened and run change detection afterwards. If you interact (for example pass callbacks) with code that runs outside Angulars zone because the code was initialized outside your Angular application or because it uses some async API that is not covered by zone.js, then Angular doesn't get notified when "something" happenend and doesn't run change detection. With `zone.run()` you "force" execution back into Angulars zone to get change detection executed. – Günter Zöchbauer Nov 22 '16 at 05:54
0

Try using Zone. You can find the discussion about this here https://forum.ionicframework.com/t/taken-image-from-camera-not-able-to-show-in-ui/44487

Tuong Le
  • 18,533
  • 11
  • 50
  • 44