[SOLVED]No dynamically changes on pushed page

First of all, I’m new in AngularJS, Ionic and mobile programming, so be kind. I googled this and have no answer.

I’m programming a bluetooth app to control and view custom robot state. In the home page I’m listing bluetooth devices and once I select a device and connect I push to ControlPage. I have test (simulate) changes with this ControlPage as root and it works perfect, dynamic simulated changes are performnt in browser and in my phone. But when I use HomePage, select the device and connect, no changes in the view are performed. State variables change and data is send to the robot, but I’ve no live refresh from the components.

I paste some of the code:

HomePage

import { Component } from '@angular/core';
import { NavController, AlertController } from 'ionic-angular';
import { AndroidFullScreen } from '@ionic-native/android-full-screen';
import { BluetoothSerial } from '@ionic-native/bluetooth-serial';
import { ControlPage } from '../control/control';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})

export class HomePage {
  devices = {
    paired: null,
    unpaired: null,
    scanning: false
  };

  mostrar = {
    conocidos: "none",
    disponibles: "none"
  };

  constructor(public navCtrl: NavController,
              private alertCtrl:AlertController,
              private bluetoothSerial: BluetoothSerial,
              private androidFullScreen: AndroidFullScreen) {
                this.androidFullScreen.isImmersiveModeSupported()
                  .then(() => this.androidFullScreen.immersiveMode())
                  .catch((error: any) => console.log(error));
                this.bluetoothSerial.enable();
                this.devices.paired = null;
                this.devices.unpaired = null;
                this.devices.scanning = false;
                //this.getBluetoothDevices("all");
  }

  scanAllDevices() {
    if(this.devices.scanning === false) {
      this.devices.paired = null;
      this.devices.unpaired = null;
      this.mostrar.conocidos = "none";
      this.mostrar.disponibles = "none";
      this.getBluetoothDevices("all");
    }
  }

  getBluetoothDevices(from) {
    if(this.devices.scanning === false) {
      this.bluetoothSerial.isEnabled().then(data => {
        if(data){
          if(from === "paired" || from === "all") {
            this.devices.paired = null;
            this.bluetoothSerial.list().then(pairedDevices=> {
              if(pairedDevices!= null){
              if(pairedDevices.length > 0){
                this.devices.paired = pairedDevices;
                this.mostrar.conocidos = "inline";
              }}
            });
          }
          if(from === "unpaired" || from === "all") {
            this.devices.unpaired = null;
            this.devices.scanning = true;
            this.bluetoothSerial.discoverUnpaired().then((unpairedDevices) => {
              if(unpairedDevices!= null){
              if(unpairedDevices.length > 0){
                this.devices.unpaired = unpairedDevices;
                this.mostrar.disponibles = "inline";
              }}
              this.devices.scanning = false;
            });
          }
        }
      }).catch(err => {
        let alert = this.alertCtrl.create({
          title: 'Bluetooth',
          subTitle: 'Verifique su conexión bluetooth.',
          buttons: ['Descartar']
        });
        alert.present();
      });

    } else {
      let alert = this.alertCtrl.create({
        title: 'Bluetooth',
        subTitle: 'Scaneando...',
        buttons: ['Descartar']
      });
      alert.present();
    }
  }

  success = (data) => {
    this.bluetoothSerial.isConnected().then(() => {
      this.navCtrl.push(ControlPage, {
        bluetoothSerial: this.bluetoothSerial
      });
    });
  }

  fail = (error) => {
    let alert = this.alertCtrl.create({
      title: error,
      message: 'No hay conexión con este dipositivo',
      buttons: [
        {
          text: 'Cancelar',
          role: 'cancel',
          handler: () => {
            this.bluetoothSerial.disconnect();
          }
        }
      ]
    });
    alert.present();
  }

  connectTo(device: any) {
    let alert = this.alertCtrl.create({
      title: device.name,
      message: '¿Se desea conectar con este dispositivo?',
      buttons: [
        {
          text: 'Cancelar',
          role: 'cancel',
          handler: () => {

          }
        },
        {
          text: 'Conectar',
          handler: () => {
            this.bluetoothSerial.connect(device.address).subscribe(this.success, this.fail);
          }
        }
      ]
    });
    alert.present();
  }
}

ControlPage:

import { Component } from '@angular/core';
import { NavParams } from 'ionic-angular';
import { BluetoothSerial } from '@ionic-native/bluetooth-serial';

@Component({
  selector: 'page-control',
  templateUrl: 'control.html'
})

export class ControlPage {

  colorRunStop : string = "secondary";
  iconRunStop : string = "play";

  constructor(private navParams: NavParams) {
    this.bluetoothSerial = navParams.get('bluetoothSerial');
    this.robot.memory = new Uint8Array(256);
    this.robot.registers = new Uint8Array(16);
    this.getName();
    this.bluetoothSerial.subscribeRawData().subscribe((data) => {
      if(this.state.gettingName) this.stateGettingName(new Uint8Array(data));
    });
  }

  ionViewWillLeave() {
    this.bluetoothSerial.disconnect();
  }

  stateGettingName(bytes : Uint8Array) : void {
    for(var i=0; i < bytes.length && this.state.gettingName; ++i) {
      if(!this.state.retrievingData) {
        if(bytes[i] == this.commands.START) {
          this.state.retrievingData = true;
        }
      } else if(bytes[i] != this.commands.STOP) {
        this.robot.name += String.fromCharCode(bytes[i]);
      } else {
        this.state.gettingName = false;
        this.state.retrievingData = false;
      }
    }
  }

  getName() : void {
    this.bluetoothSerial.write([this.commands.GETNAME]);
    this.state.gettingName = true;
  }

  actionRunStop() : void {
    if(this.state.running) {
      this.iconRunStop = "play";
      this.colorRunStop = "secondary";
      this.showingElements = "inline";
      this.state.running = false;
    } else {
      //this.bluetoothSerial.write([this.commands.RUN]);
      this.state.gettingRegisters = true;
      this.state.gettingMemory = true;
      this.state.gettingPC = true;
      this.state.gettingIR = true;
      this.iconRunStop = "remove-circle";
      this.colorRunStop = "danger";
      this.showingElements = "none";
      this.state.running = true;
    }
    alert("iconRunStop: "+this.iconRunStop+"\n"+
          "colorRunStop: "+this.colorRunStop+"\n"+
          "showingElements: "+this.showingElements+"\n"+
          "showingSpinner: "+this.showingSpinner+"\n"+
          "state.running: "+this.state.running);
  }
}
<ion-header>
  <ion-navbar color="primary">
    <ion-title>
      Conectado
    </ion-title>
  </ion-navbar>
</ion-header>
<ion-content padding>
  <ion-list [style.display]="showingElements" no-lines>
    <ion-item>
      <ion-label class="titles" stacked>Nombre del robot</ion-label>
    </ion-item>
    <ion-item>
      <ion-label class="bot-info" >{{ robot.name }}</ion-label>
    </ion-item>
    <ion-item>
      <ion-label class="titles" stacked>Memoria principal</ion-label>
    </ion-item>
    <ion-item>
      <ion-label class="bot-info">{{ change.mem }}</ion-label>
      <button ion-button round color="dark" type="button" item-right>
        <ion-icon name="open"></ion-icon>
      </button>
    </ion-item>
    <ion-item>
      <ion-label class="titles" stacked>Registros</ion-label>
    </ion-item>
    <ion-item>
      <ion-label class="bot-info">{{ change.reg }}</ion-label>
      <button ion-button round color="dark" type="button" item-right>
        <ion-icon name="open"></ion-icon>
      </button>
    </ion-item>
    <ion-item>
      <ion-label class="titles" stacked>Contador de programa</ion-label>
    </ion-item>
    <ion-item>
      <ion-label class="bot-info">{{ change.pc }}</ion-label>
    </ion-item>
    <ion-item>
      <ion-label class="titles" stacked>Registro de Instrucción</ion-label>
    </ion-item>
    <ion-item>
      <ion-label class="bot-info">{{ change.ir }}</ion-label>
      <button ion-button round color="dark" type="button" item-right>
        <ion-icon name="open"></ion-icon>
      </button>
    </ion-item>
  </ion-list>
  <div *ngIf="showingElements == 'none'" >
    <ion-spinner name="bubbles" ></ion-spinner>
    <div class="spinnerText"> Ejecutando...</div>
  </div>
</ion-content>

<ion-footer no-shadow>
  <ion-grid>
    <ion-row justify-content-around>
      <ion-col>
        <div align="center">
          <button ion-button icon-only [color]="colorRunStop" full clear (click)="actionRunStop()" >
            <ion-icon [name]="iconRunStop"></ion-icon>
          </button>
        </div>
      </ion-col>
      <ion-col>
        <div align="center">
          <button ion-button icon-only color="energized" full clear (click)="actionStep()" [disabled]="state.running" >
            <ion-icon name="skip-forward"></ion-icon>
          </button>
        </div>
      </ion-col>
      <ion-col>
        <div align="center">
          <button ion-button icon-only color="dark" full clear [disabled]="state.running" >
            <ion-icon name="repeat"></ion-icon>
          </button>
        </div>
      </ion-col>
    </ion-row>
  </ion-grid>
</ion-footer>

In the code above the running state do not show the spinner. But when ControlPage is the root page it works… I don’t know what i’m doing wrong. And when I go back to the HomePage the spinner appears for a second in the leaving ControlPage. ¯_(ツ)_/¯

Please, help me! You’re my only hope.

PS: sorry about my english.


@AaronSterling was right, but i don’t understand why in the root page works without NgZone.

(...)
  constructor(private navParams: NavParams, zone : NgZone) {
(...)
//in some action performed:
this.zone.run( () => { 
  //changing values...
}

I suppose there is a better way to do this…

That’s an old framework. The new, not reverse compatible framework, is called Angular (formerly Angular 2).

Your code is very hard to read. You might want to improve your style, at least for my sanity if not yours. But probably what is happening is that you’re updating variables outside the Angular zone, so Angular does not notice they are updated. Angular change detection listens to very specific things. So I’d suggest you read more about change detection.

Thanks for your reply. Didn’t know that AngularJS it’s the old name, acknowledged. But, why it works when it’s the root page, and when it’s the pushed page doesn’t? That’s why I’m so confused.

Sorry if the source is a little messy, it’s work in progress. :stuck_out_tongue_winking_eye:

Hello,
did you try to scan for the devices in : ionViewWillEnter ?

The bluetooth works fine, the devices listing and connecting… My problem was that the robot was sending me the status (the data was recibed but no refresh in the labels at the view). But using this.zone.run(() => { /* put recibed data in the variables */ }); works flowlessly. Now my app it’s almost done. Later I’ve to beautify my code, so the world can read it and understand it hahaha.

1 Like

Ok let me see how it’s working later, i like robots :slight_smile: