Ionic-native: Interpolation/Change Detection not working

Created on 28 Oct 2016  路  5Comments  路  Source: ionic-team/ionic-native

_From @BAWES on October 28, 2016 18:43_

Short description of the problem:

I've setup the native Keyboard plugin to update a boolean variable in the component which should be displayed on the page via interpolation. The keyboard events work perfect, the variable is being updated, however the view remains with the old value until some other interpolated variable changes in that view.

What behavior are you expecting?

Updated value of the variable shown in the view

Steps to reproduce:

  1. I've pasted in the code which reproduces the issue.
  2. I'm testing it on my Galaxy S7 Edge Phone (Android) via ionic run android --livereload
// Core
import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';
// Services
import { AuthService } from '../../../providers/auth.service';
import { KeyboardService } from '../../../providers/keyboard.service';
// Pages
import { RegisterPage } from '../register/register';
// Forms
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
// Native 
import { Keyboard } from 'ionic-native';

/*
  Login Page
*/
@Component({
  selector: 'page-login',
  template: `

<ion-content class='contentArea' padding>

  <ion-card class='loginCard'>

    <h1>Keyboard Opened? {{ isKeyboardOpen }}</h1>
    <p>The above doesn't Interpolate until the value below refreshes</p>
    <p>Try opening and closing the keyboard via the input below and check results</p>

    <ion-title>2-sec Boolean Toggle: {{ randomBoolean }} </ion-title>

    <ion-card-content class='authArea'>

      <!-- Login Form -->
      <form [formGroup]="loginForm" (ngSubmit)="onSubmit()" class="classicInput" novalidate>

        <input type="email"
          formControlName="email"
          placeholder="Your Email Address"/>

        <input type="password"
          formControlName="password"
          placeholder="Your Password"/>

        <div text-center>
          <button ion-button block outline color="dark" type="submit" [disabled]="!loginForm.valid"
            [style.background-color]="loginForm.valid?'black':'white'"
            [style.color]="loginForm.valid?'white':'black'">
            Sign in
          </button>
        </div>

      </form>

      </ion-card-content>

  </ion-card>


</ion-content>
  `
})
export class LoginPage {

  public loginForm: FormGroup;

  public randomBoolean = false;

  public isKeyboardOpen = false;
  public keyboardHeight = 0;

  constructor(
    public navCtrl: NavController, 
    private _fb: FormBuilder,
    public keyboard: KeyboardService
    ){}


  ionViewDidLoad() {
    // Initialize the Login Form
    this.loginForm = this._fb.group({
      email: ["", Validators.required],
      password: ["", Validators.required]
    });

    // Subscribe to Keyboard Visible Events
    Keyboard.onKeyboardShow().subscribe(e => {
      this.isKeyboardOpen = true;
      this.keyboardHeight = e.keyboardHeight;
    });

    // Subscribe to Keyboard Closed Events
    Keyboard.onKeyboardHide().subscribe(e => {
      this.isKeyboardOpen = false;
    });

    this.infiniteLoop();
  }

  infiniteLoop(){
    this.randomBoolean = ! this.randomBoolean;

    setTimeout(()=>{
      this.infiniteLoop();
    }, 2000);
  }


  onSubmit(){
    console.log(JSON.stringify(this.loginForm.value));
  }


}

Which Ionic Version? 1.x or 2.x
Latest 2.x

Run ionic info from terminal/cmd prompt: (paste output below)
Cordova CLI: 6.3.1
Gulp version: CLI version 1.2.1
Gulp local:
Ionic Framework Version: 2.0.0-rc.1
Ionic CLI Version: 2.1.1
Ionic App Lib Version: 2.1.1
Ionic App Scripts Version: 0.0.34
ios-deploy version: 1.8.6
ios-sim version: 5.0.8
OS: Mac OS X El Capitan
Node Version: v6.7.0
Xcode version: Xcode 8.1 Build version 8B62

_Copied from original issue: driftyco/ionic#8945_

Most helpful comment

_From @BAWES on October 28, 2016 20:40_

Not sure where the core of the issue is originating from, but found out that change detection wasn't functioning correctly and solved it by triggering the detection manually.

My workaround:

  • import { ApplicationRef } from '@angular/core';
  • constructor(private ref:ApplicationRef) {

Then trigger the change detection as follows:

Keyboard.onKeyboardShow().subscribe(e => {
      this.isKeyboardOpen = true;
      this.keyboardHeight = e.keyboardHeight;

      // Force Change Detection in Angular
      this.ref.tick();
    });

All 5 comments

_From @BAWES on October 28, 2016 20:40_

Not sure where the core of the issue is originating from, but found out that change detection wasn't functioning correctly and solved it by triggering the detection manually.

My workaround:

  • import { ApplicationRef } from '@angular/core';
  • constructor(private ref:ApplicationRef) {

Then trigger the change detection as follows:

Keyboard.onKeyboardShow().subscribe(e => {
      this.isKeyboardOpen = true;
      this.keyboardHeight = e.keyboardHeight;

      // Force Change Detection in Angular
      this.ref.tick();
    });

Hello, this is most likely an issue caused by the change from the keyboard plugin not running in a zone. Zone.js is the library that runs change detection in Angular 2. If an event is not async then it will not trigger a zone update. I am going to move this issue to the ionic native repo since this is related to an ionic native plugin. Thanks!

I'm having similar issues with the BLE plugin. My current guess is that change detection is not triggered _at all_ for methods returning Observables. See also https://forum.ionicframework.com/t/does-ionic-native-really-ensure-that-native-events-trigger-change-detection-in-angular-2/69993

@tkem You are a life saver, I was beating my head for the last 2 hours about this with BLE

It would be better to use ChangeDetectorRef.detectChanges(), since that will do change detection only on the component and it's children.

ApplicationRef.tick() will do change detection on the entire component tree, I believe.

I've opened a separate issue to see about getting change detection triggered automatically when observables return: https://github.com/driftyco/ionic-native/issues/823

Was this page helpful?
0 / 5 - 0 ratings