View not refreshed after Model changes

#1

Hi all, I’m updating the model within the constructor of my class, but the changes on the model are not visible, when clicking something or navigating back, the fields are updated.

The stuff done in the class:

constructor(public navCtrl: NavController, public navParams: NavParams, public loadingCtrl: LoadingController, public alertCtrl: AlertController, public profilData: ProfilData, public authData: AuthData) {
this.loading = this.loadingCtrl.create({
  content: 'Lade Daten',
  dismissOnPageChange: true
});
this.loading.present();

this.navCtrl = navCtrl;
this.profilData = profilData;

// Data is loaded async. The userProfil is used by the model
this.profilData.getUserProfile().on('value', (data) => {
  this.userProfile = data.val();
  this.birthDate = this.userProfile.birthDate;
  this.loading.dismiss();
});

}

A snippet of the view:

`<ion-item (click)="updateName()">
  <ion-grid>
    <ion-row>
      <ion-col width-50>
        Name
      </ion-col>
      <ion-col width-50 *ngIf="userProfile?.firstName || userProfile?.lastName">
        {{userProfile?.firstName}} {{userProfile?.lastName}}
      </ion-col>
      <ion-col class="placeholder-profile" *ngIf="!userProfile?.firstName">
        <span>
          Ändern
        </span>
      </ion-col>
    </ion-row>
  </ion-grid>
</ion-item>`

System information:
Your system information:

You have been opted out of telemetry. To change this, run: cordova telemetry on.
6.5.0

Ionic Framework Version: 2.0.0
Ionic CLI Version: 2.2.1
Ionic App Lib Version: 2.2.0
Ionic App Scripts Version: 1.0.0
ios-deploy version: Not installed
ios-sim version: Not installed
OS: Windows 7
Node Version: v7.4.0
Xcode version: Not installed

Thx!

#2

ProfilData does not look idiomatic. Ordinarily such services return futures such as Observables or Promises, and if you make it do that, things should start working as you expect.

#3

Hi,it’s an firebase service, see how PrfilData is called:

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


@Injectable()
export class ProfilData {
 // Create a database reference to the userProfile node
userProfile: any;
// Create an auth reference to the logged user
currentUser: any;

/** 
* Create the references from above
*/
constructor(public http: Http) {
this.currentUser = firebase.auth().currentUser;
this.userProfile = firebase.database().ref('/userProfile');
}

/** 
* This function returns a Database reference to the userProfile/uid
* of the current user an we'll use it to get the user profile in our page
*/
getUserProfile(): any {
return this.userProfile.child(this.currentUser.uid);
}

Firebase is delivering promises… or did I missunderstood something?

#4

I have no idea, never used it. If it is, though, then instead of

on('value', (data) => {

You would want something like

then((data) => {

Somebody who uses Firebase can probably chime in on which Angular2 shims do what; there must be one that papers over all of this for you.

#5

one solution is to wrap it in a zone… not sure it is the best, but it will work.

import {NgZone} from '@angular/core';

Be sure to add to constructor…

constructor(private zone: NgZone) {}

use in callback

// Data is loaded async. The userProfile is used by the model
this.profilData.getUserProfile().on('value', (data) => {
  this.zone.run(() => {
     this.userProfile = data.val();
     this.birthDate = this.userProfile.birthDate;
     this.loading.dismiss();
  })
});

Also I would move the code out of the constructor

#6

I hate disagreeing with @aaronksaunders, but I feel strongly that direct use of zones in client code should be discouraged. As far as is humanly possible, zones should be treated as an opaque implementation detail of Angular and all interaction with them should be isolated to shim libraries that wrap and return zone-aware futures.

1 Like
#7

@rapropos you are right “one solution is to wrap it in a zone… not sure it is the best, but it will work.”

However… after further research, it appears that there are known issues with how firebase functions to provide realtime updates, ie it runs outside of Angular2 default zone, so it appears that your choice is to use the suggestion I have provided, port it to angularfire… where they have resolved the issue or come up with a more complex solution using observables.

@sissifd see links I have provided

1 Like
#8

I think this is really the best solution, which is what I was implying about shim libraries. I do not have any knowledge as the pros and cons of options here, if there are even multiple such.