Data binding with [(ngModel)] and *ngFor results in empty array

I try to load and bind this.studentNames[i].checked to prepare checkboxes (key-value pair in localstorage if checkbox is set). However, after correctly pushing the entries from the storage in the this.studentNames array (I can see all of them as in the storage in the view), the this.studentNames array is then empty [] in the array and hence not longer accessable for the model.

My view:

<ion-list>
  <ion-item *ngFor="let studentName of studentNames; let i=index">
    <ion-label>{{studentNames[i].name}}</ion-label>
    <ion-checkbox [(ngModel)]="studentNames[i].checked" (ionChange)="checkboxToggle($event,studentNames[i])"></ion-checkbox>
  </ion-item>
</ion-list>

My model:

@mycomp...
selectedItem: any;
studentNames: Array<{id: string, name: string, checked: boolean}>;

constructor(private navParams: NavParams, public storage: Storage) {
    // If we navigated to this page, we will have an item available as a nav param
    this.selectedItem = navParams.get('item');
    this.studentNames = [];
    this.readStorageAtStartup();
    console.log(this.studentNames)
  }

  public readStorageAtStartup() {
    this.storage.ready().then(() => {
       this.storage.forEach( (value: string, key: string, index: number) => {
         if(key.charAt(0)=="S") {
           this.studentNames.push({id: key, name: value, checked: true})
         }
       })
    })
  }

Console.log():

Array [  ]

What am I doing wrong? Thanks for your help!

If you do a console.log immediately after an asynchronous function, obviously the Array will be empty. You can add the console.log after the forEach

public readStorageAtStartup() {
   this.storage.ready().then(() => {
     this.storage.forEach( (value: string, key: string, index: number) => {
       if(key.charAt(0)=="S") {
         this.studentNames.push({id: key, name: value, checked: true})
       }
     });
     console.log(this.studentNames);
   })
}

And try to check if the condition you have (key.charAt(0) == "S") is valid

This is what happens with your code:

this.studentNames = []; Processing… DONE
this.readStorageAtStartup(); Processing…
console.log(this.studentNames) Processing… DONE
this.readStorageAtStartup(); DONE

A then() method works asynchronous, it means that when your array gets logged, it hasn’t finished processing yet.

1 Like

Thanks, condition is valid. Inserting the console.log() as you proposed ends up in an empty array, too.

@anderl80 Try to log each item in the forEach to see if the storage retrieve some item and if the keys and values are the ones you expect. Something like:

public readStorageAtStartup() {
	this.storage.ready().then(() => {
		this.storage.forEach((value: string, key: string, index: number) => {
			console.log('key', key);
			console.log('value', value);

			if (key.charAt(0) == "S") {
				this.studentNames.push({ id: key, name: value, checked: true })
			}
		});
		
		console.log('studentNames', this.studentNames);
	})
}