Assign value to variable from service ionic 2


#1

Hello everybody:

I’m trying to set a value in ionic 2, taking the value from a mock service, but when I try to get the value of the object outside the then, tells me that it’s undefined

The code involved is:

saveCar(data) {
    this.carInfo = data;
  }

ngAfterViewInit() {
    this.carService.getInfo(this.picture).then((data) => {
      this.saveCar(data);
    });
    console.log(this.carInfo);
  }

I’ve tried to set the value without calling a function, and the result it’s the same.

Do you have any ideas?

Thank you for your help.

Regards.


#2

Seems fair to me that it tells you it’s undefined :smile: If you’re sure that data is indeed returned, move the logging somewhere else. Log this.carInfo after you’ve saved it, then it’ll show your data returned from the Promise.

// first we retrieve the data
ngAfterViewInit() {
    this.carService.getInfo(this.picture).then((data) => {
  // here we're receiving data from the promise      
     this.saveCar(data);
  });
}
saveCar(data) { // Now we're getting here from within the then
   this.carInfo = data; // data get's assigned to this.carInfo instance
   console.log(this.carInfo); // log the carInfo
}

#3

Yes, I didn’t get corretly the concept of async :grinning:

Very thank you!


#4

Anyway, after this problem is solved, The information that I want to show in the html does not appear.

<ion-row *ngIf="carInfo != null">
    <ion-item>
      <ion-label fixed>Car Plate</ion-label>
      <ion-input type="text" [(ngModel)]="carInfo.plate" placeholder="plate"></ion-input>
    </ion-item>
</ion-row>

Why is not updated?

Thanks


#5

Works for me, so the bug must be somewhere outside what you’ve posted here:

Observable.of({plate: 'abc123'}).delay(2000).subscribe(ci => this.carInfo = ci);

Your exact template code, and after 2 seconds I see “Car Plate abc123”.


#6

It wasn’t a bug at all, the view didn’t update after getting the information.

My solution was to use ngZone when updating the value:

  saveCar(data) {
    this._ngZone.runOutsideAngular(() => {
      this.carInfo = data;
      this._ngZone.run(() => { console.log("Updated value: " + this.carInfo) });
    });
  }

Thank you for your help!


#7

Sorry, but that’s not the proper solution. If you have to manually be messing with zones, you are not feeding the data properly. This is going to continue being a problem until you resolve the ultimate issue, and band-aiding things with zone.run() and setTimeout() is not the way to go.


#8

Why am I not getting the data properly? Where do I have to put your code line? The code related to the service is the following (now I’m dealing only with mock data):

  getInfo(picture): Promise<CarInfo> {
    return Promise.resolve(this.car);
  }

Thank you in advance.


#9

Please post the entire CarService.


#10
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';


export class CarInfo {
  plate: string;
  brand: string;
  model: string;
}

@Injectable()
export class CarInfoDetection {
  car: CarInfo;
  constructor(public http: Http) {
    console.log('Hello CarInfoDetection Provider');
    this.car = { 'plate': "12312312", 'brand': 'BMW', 'model': "X1" }
  }

  getInfo(picture): Promise<CarInfo> {
    return Promise.resolve(this.car);
  }
}

#11

I add that provider verbatim to my vanilla tabs scratch project, add it to the providers of my app module, change my home page to look like this:

constructor(private _cars: CarInfoDetection) {}
ngAfterViewInit() {
  this._cars.getInfo(null).then(ci => this.carInfo = ci);
}

No messing with zones, “Car Plate 12312312” shows up as expected.


#12

mmmmm… Now it works. The only change I’ve made is that now I don’t use ngModel , I use only read-only bindings

<ion-card-content>
      <ion-item>
        <h2>Car Plate:</h2>
        <p>{{carInfo.plate}}</p>
      </ion-item>
      <ion-item>
        <h2>Brand:</h2>
        <p>{{carInfo.brand}}</p>
      </ion-item>
      <ion-item>
        <h2>Model:</h2>
        <p>{{carInfo.model}}</p>
      </ion-item>
    </ion-card-content>

The code related with the service and with the component was the same. Also I’ve changed the code only to use ngModel and the result works. Seems weird.

Anyway, thank you for your help