Object created and assigned in ts file but became undefined

Here is the background info that I’m using:
ionic - v2.2.1
node - v6.9.5
cordova - v6.5.0

I have successfully retrieved my object via SQLite in the .ts file.

selector: ‘page-field-info’,
templateUrl: ‘field-info.html’
export class FieldInfoPage {
field: any;
client: any;
crop: any;

  constructor(public navCtrl: NavController, public navParams: NavParams, public modalCtrl: ModalController, public database: Database) {
    this.field = navParams.get('field');

    this.database.getClientById(this.field.clientId).then((result) => {
        if(result != null) {
          this.client = result;
          console.log("@@@ LOG::field-info.ts: ");
    }, (error) => { console.log("ERROR::FieldInfoPage::getClientById: ", error); });

    this.database.getCropTypeById(this.field.cropId, "en").then((result) => {
        if(result != null) {
          this.crop = result;
    }, (error) => { console.log("ERROR::FieldInfoPage::getCropTypeById: ", error); });


On my html, I just try to reference it, but it seems to be undefined.
Here is my html page reference.

<ion-content padding class="body">
    <ion-card-header><h1>Field Information</h1></ion-card-header>
      <p>Client: {{client.clientId}}</p>
      <p>Client Rep: {{client.name}}</p>


Here is the log I received.

@@@ LOG::getClientById:: SQL = SELECT DISTINCT * FROM CLIENT WHERE CLIENT_ID = 1 main.js:18842
database already open: data.db SQLitePlugin.js:168
@@@ LOG::ionViewDidLoad: Client:  main.js:57833
undefined main.js:57834
@@@ LOG::getAllClients::Returned rows = 1 main.js:18860
No rows affected! main.js:18873
@@@ LOG::field-info.ts:  main.js:57811
Object {clientId: 1, name: "Mr. Jenkins", company: "Happy Farms"} 

Am I missing something? I was under the impression if I got the object in the ts file, I should be able to access it on my html; however, I’m confused as why it’s not working.

thank you for your time in advance.

It’s not working because of timing. The template will attempt to access it before your read from storage has resolved. There are a bunch of ways to work around this: I think the simplest and sanest is to initialize it to a viable dummy value in the constructor. I would also strongly recommend defining and using business logic interfaces instead of falling back on the any crutch.

My personal recommendation is to:

  1. Define an @Injectable - service class
  2. Extract all the database query methods into this service class
  3. Use Rx/JS Observable - and expose data access methods from this service class to return Observable
  4. Get the Service object through Dependency Injection in the Component Class
  5. Subscribe to the Observable for data update
  6. use *ngIf and display only when there is ‘Client’ object value (probably check for null or something based on your data)

This way, it’d help maintaining good separation of concerns in design as well as handling UI separately from the data services.
Check for Rx/JS here: http://reactivex.io/rxjs/class/es6/Observable.js~Observable.html

Timing…that’s what I was suspecting; however, I thought the asynchronous would avoid such issue? I probably don’t understand the concept well enough. So how do I initialize a viable dummy value? Sorry I’m new to this, need some hand holding.

client = {clientId: '', name: 'loading'};

Hi neelavar,
Thank you very much for your detail reply. I’m very new to this, so don’t really understand well enough to grasp the information. I currently use a provider class where I define all my database queries in the database.ts. Does this meet your definition of service class? Wrt 3rd point, what’s Rx/JS Observable? It seems like a new class, but does that mean I have to re-write my current code completely to incorporate this? Thanks a lot in advance.

Based on what you just posted, it might take you a few weeks to get your head around the approach suggested by @neelavar. But it’s worth it. That said, the advice from @rapropos will get you working code a lot faster.