0

I've just started working with the Ionic framework. Until now, I've gotten along okay-ish. My problem is that an array gets nulled at runtime and I can't figure out why. I'm stumped. I think, for this question, it's better to post my code first.

    export interface Days
{
  name:string;
}

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage
{
  days = [] as Days[];
  constructor(public navCtrl: NavController, public alertCtrl: AlertController, public navParams: NavParams)
  {

  }

  presentDayDialog(): void
  {
    let alert = this.alertCtrl.create({
      title: 'Add new day',
      message: 'Enter a name for the new day',
      inputs: [
        {
          name: 'day',
          placeholder: 'Day'
        },
      ],
      buttons: [
        {
          text: 'Cancel',
          handler: () => {
            console.log('Cancel clicked');
          }
        },
        {
          text: 'Save',
          handler: data => {
            this.addDays(data.day);
          }
        }
      ]
    });
    alert.present();
  }

  addDays(rname): void
  {
    this.days.push({name: rname});
  }

  itemTapped(Days)
  {
    this.navCtrl.push(RoutinePage, {
      pageName: Days.name
    });
    console.log("The page name was "+Days.name);
  }
}

export interface Routine
{
  name:string;
  weight: number;
  reps: number;
}

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

export class RoutinePage
{
  routines = [] as Routine[];
  public pageName;

  constructor(public navCtrl: NavController, public toastCtrl: ToastController, public alertCtrl: AlertController, public platform: Platform, public storage: Storage, public navParams: NavParams)
  {
    console.log('PRE CONSTRUCTOR ' + this.routines);

    this.pageName = navParams.get("pageName");
    this.getRoutines();
    console.log('POST CONSTRUCTOR ' + this.routines);
  }

  //Sets the routines to storage
  setRoutines()
  {
    console.log('ROUTINES ARRAY before setRoutine() '+ this.routines );
    this.storage.set(this.pageName, this.routines );
    console.log('ROUTINES ARRAY after setRoutine() '+ this.routines );
  }

  //Gets the routines from storage, this gets executed at the construction of this page so it isn't empty at the start
  getRoutines()
  {
    console.log('ROUTINES ARRAY before getRoutine() '+ this.routines );
    this.routines = [{name: 'Jogger', weight: 0, reps: 0}];
    this.storage.get(this.pageName).then((data) => {
      this.routines = data;
    });
    console.log('ROUTINES ARRAY after getRoutine() '+ this.routines );
  }

  //Adds a new routine and saves it to storage
  addRoutine(rname): void
  {
    console.log('ROUTINES ARRAY before addRoutine() '+ this.routines );
    this.routines.push({name: rname, weight: 0, reps: 0});
    console.log('ROUTINES ARRAY after addRoutine() ' + this.routines);
    this.setRoutines();
  }

  //Presents the dialog for adding a new routine on FAB-button-press, calls addRoutine function
  presentRoutineDialog(): void
  {
    let alert = this.alertCtrl.create({
      title: 'Add new routine',
      message: 'Enter a name for the new routine',
      inputs: [
        {
          name: 'routine',
          placeholder: 'Routine'
        },
      ],
      buttons: [
        {
          text: 'Cancel',
          handler: () => {
            console.log('Cancel clicked');
          }
        },
        {
          text: 'Save',
          handler: data => {
            console.log('ROUTINES ARRAY AFTER SAVE BUTTON PRESS:' +this.routines);
            this.addRoutine(data.routine);
          }
        }
      ]
    });
    console.log('ARRAY BEFORE ALERT: ' + this.routines);
    alert.present();
    console.log('ARRAY AFTER ALERT: ' + this.routines);    
  }  
}

So, this is how I imagine this should work. I add items (Days) to a list on the "first" page. When I click on that item, I open a second page and pass the name of the "Day", which then becomes the name of the second page. I also use this name for the key-name to store this array in the storage. So every page has it's own storage from which the page is filled with info at construction.

THE PROBLEM: The routines-Array inexplicably gets nulled at runtime, except if the name of the day of first page which I click on is empty. This propably has something to do with my hacky-feeling storage system, but I can't imagine what is the culprit, exactly. These are the console logs, which I found kinda interesting:

The page name was Upper Body home.ts:63:4
PRE CONSTRUCTOR routine.ts:28:4
ROUTINES ARRAY before getRoutine() routine.ts:46:4
ROUTINES ARRAY after getRoutine() [object Object] routine.ts:51:4
POST CONSTRUCTOR [object Object] routine.ts:32:4
ARRAY BEFORE ALERT: null routine.ts:91:4
ARRAY AFTER ALERT: null routine.ts:93:4
ROUTINES ARRAY AFTER SAVE BUTTON PRESS:null routine.ts:85:12
ROUTINES ARRAY before addRoutine() null

So, immediately after the constructor is "finished", the array is suddenly null. Why is that? What am I not seeing? I'm honestly at the end of my wits here and I was hoping someone could help.

oguz ismail
  • 1
  • 16
  • 47
  • 69
Necrophades
  • 605
  • 7
  • 21
  • 1
    What is the value of `data` here: `this.routines = data;`? – robbannn Jul 29 '17 at 00:03
  • I suspect that @robbannn has correctly pointed out the source of the issue. I'll add that the line `console.log('POST CONSTRUCTOR ' + this.routines);` does not run when you think it does. Specifically it does not display the value of `this.routines` after `getRoutines` completes but rather the value before it does, because that function is asynchronous – Aluan Haddad Jul 29 '17 at 00:46
  • Possible duplicate of [How do I return the response from an Observable/http/async call in angular2?](https://stackoverflow.com/questions/43055706/how-do-i-return-the-response-from-an-observable-http-async-call-in-angular2) – AT82 Jul 29 '17 at 07:33

1 Answers1

0

Okay, I fixed it with the help from SO. The promise returned from storage.get('ArrayKey') was null, because the storage my app tried to get didn't exist. What I did was check if the promise returned from storage.get('ArrayKey') was null. If it was, I let storage.set('ArrayKey') store the array as the value I initialized it with, which is array[] -> empty but not null. Then, I called storage.get('ArrayKey'). This now succeeded, because the Array now was empty, but not null.

With this title, I doubt anyone having the same problem will ever find this, but maybe he/she still finds it. Cheers and thank you for the help.

Necrophades
  • 605
  • 7
  • 21