Ionic 4 Tab to page then back to Tab did not trigger ionViewWillEnter [Solved]

I have an small application where user can edit their account and after edit user route back to my account page.

Situation:

My account Tab > Edit Account Page > Save and Route Back to My account Tab*

When User redirect to My account page none of the life cycle event trigger in ionic 4

Screenshoot: http://prntscr.com/oatlru [edit account page code ] , http://prntscr.com/oatlvz [My account page]

Hi Please go through it. It may help you
In summary, these are the events:

  • ionViewDidLoad : Fired only when a view is stored in memory . This event is NOT fired on entering a view that is already cached. It’s a nice place for init related tasks.
  • ionViewWillEnter : It’s fired when entering a page, before it becomes the active one. Use it for tasks you want to do every time you enter in the view (setting event listeners, updating a table, etc.).
  • ionViewDidEnter : Fired when entering a page, after it becomes the active page . Quite similar to the previous one.
  • ionViewWillLeave : Fired when you leave a page, before it stops being the active one. Use it for things you need to run every time you are leaving a page (deactivate event listeners, etc.).
  • ionViewDidLeave : Fired when you leave a page, after it stops being the active one. Similar to the previous one.
  • ionViewWillUnload : Fired when a view is going to be completely removed (after leaving a non-cached view).

Reference : https://ionicframework.com/blog/navigating-lifecycle-events/

2 Likes

None of the event work when back from page to tab

my my-account tab

ionViewWillEnter() {
    this.getUser();
    console.log('ionViewWillEnter ')
  }

    ionViewDidLoad() {
    console.log('ionViewDidLoad ')
    }
    ionViewDidEnter() {
    console.log('ionViewDidEnter ')
    }
    ionViewWillLeave() {
    console.log('ionViewWillLeave  ')
    }
    ionViewDidLeave() {
    console.log('ionViewDidLeave   ')
    }
    ionViewWillUnload() {
    console.log('ionViewWillUnload    ')
    }

Check the bellow demo

I may be wrong.
What I understood is.

Your tabs is in one container .
Now when you clicked on Edit Profile you are moving from one container to another container.
So once you come back try to call methods in container and not in tabs.

I think you are right but if i redirect to different tabs page it works perfectly. In my situation its not working with the last page.
is there any way how i can achieve what i want to do.

image

Some Possible Solutions Can be

1.If on Edit Profile Page you are saving data on server once updation in profile done. Then you can access it again once you redirected to My account Page by calling api.

2.If its working with all pages then check router configurations

  1. I m doing that but the issue is when i came back from edit page its not triggering any event, so when it it come back from edit page api call is not made by the app and the data not updated.

Same type of situation:
Lets say a news app

Page 1: List of news
Page 2: Single news

When you go to Page 2 from Page 1 and the back to page 1 by pressing any back button the content of page not refreshing.

1.When you clicking on back button and redirected to Page 1 I think its not reloading. It just showing cached copy

2.If you use routing and load it fresh I think that time it can trigger events

On back button try to routing.

image

Able to fix the issue with this.

4 Likes

Hi @rakesh_appycodes

I know you have solved this issue but I am having this exact issue at the moment and couldn’t solve it with your proposed solution. Some questions I have:

  1. Can you show us the app routing definition?
  2. Is the Edit Account form page setup as its own module?

Thanks

Not that anybody need care about my opinion, but for what it’s worth, I think lifecycle events should not be (ab)used to solve the general problem of “displaying stale data”. What people tend to do:

interface Profile {
  name: string;
 // ...
}
class ProfileService {
  profile: Profile;
}
class ProfileDisplayPage {
  profile: Profile;
  constructor(private profiler: ProfileService) {}
  ngOnInit(): void { this.profile = this.profiler.profile; }
}
class ProfileEditPage {
  profile: Profile;
  constructor(private profiler: ProfileService) {}
  updateProfile(): void { this.profiler.profile = this.profile; }
} 

…then they ask “how do I force reloading of ProfileDisplayPage?”

What I do is to leverage RxJS to solve the problem of “how do I ensure that updates propagate easily and efficiently across my app?”:

class ProfileService {
  profile$ = new BehaviorSubject<Profile | null>(null);
  watchProfile(): Observable<Profile | null> { return this.profile$; }
  peekProfile(): Profile | null { return this.profile$.value; }
  pokeProfile(profile: Profile): void { this.profile$.next(profile); }
}
class ProfileDisplayPage {
  profile$: Observable<Profile | null>;
  constructor(private profiler: ProfileService) { this.profile$ = profiler.watchProfile(); }
}
class ProfileEditPage {
  profile: Profile;
  constructor(private profiler: ProfileService) { this.profile = profiler.peekProfile(); }
  updateProfile(): void { this.profiler.pokeProfile(this.profile); }
}

There are a myriad of options for accessing Observables from a template. Many of them involve memory leaks or overly verbose boilerplate. Two that don’t are the AsyncPipe and NetanelBasal’s ngx-take-until-destroy.

I frequently think in terms of “WORM (Write Once / Read Multiple) brokers”, where a resource has many readers and a single writer. The broker in this case is the ProfileService, which is injected by anybody interested in the Profile resource. It exposes three operations: watch, peek, and poke. Readers who want updates want watch. Transient readers that don’t care about updates can use peek. Writers generally take a snapshot with peek, modify it, and push the updates back with poke.

All of this happens with no additional code on the part of readers, no dependencies on the vagaries of framework internals (such as what lifecycle events fire when on what UI components), and no wasteful performance hits (such as you see with “solutions” to this problem that completely rerender a bunch of irrelevant stuff, often via action-at-a-distance).

It is also easy (and transparent) to add network and/or backing on-device storage to ProfileService. Nobody outside that class has to know or care when or how external forces collude to bring fresh data.

26 Likes

What happen if you want to implement some logic over data received?, I mean when profile$ property of ProfileDisplayPage is updated and I want to use new data to do another operations?

profile$ is an Observable, so you could subscribe to it, or you could pipe necessary transformation operators off of it and then subscribe to that.

1 Like

yeah, but I currently have problems when I wrap the subscribed data in ngIf wrapper, Template is rendered twice, if I remove ngIf It works. Would you be so kind as to review my case?

There doesn’t seem to be enough code in there to reproduce your problem. Do you have a link to a stackblitz or github repo?

I tried to put it on stackblitz but it’s complicated, Some packages are unsatisfied :confused: I’ll try other options.

Hi there.
I read this read thread and I think I bumped into a similar situation. Like you’ve said, I want the updates to propagate across my app. I am not able to understand despite the long explanations cause I am new to ionic.

My case: It is a quiz app. There are ten levels and each level has 10 questions. Cards have been employed to contain the quiz question for each level (so, there are 10 cards for 10 levels).
In a level, if you score five or six you get a star remark for that level, if you score 7 or eight you get 2 stars and, 3 stars for 9 and 10 points. Here I am using ion-icon fora assigning stars for each level.

So the thing here is, I am not able to display the stars even when I scored the minimum point to obtain at least one star. I am sure that it’s the problem of data updates. Although the points are updated in the database(SQLite DB), I am not able to render the stars on the page.

Below is the .HTML file:

<ion-header [translucent]="true">
  <ion-toolbar>
    <ion-buttons slot="end">
      <ion-button color="primary" expand="full" routerLink="/instructions">
        <ion-icon name="information-circle" style="font-size: 25px"></ion-icon>
      </ion-button>
    </ion-buttons>
    <ion-title style="color:dodgerblue;font-family: DDC_Uchen" size="medium">
      རིག་བསྡུར
    </ion-title>
  </ion-toolbar>
</ion-header>

<ion-content [fullscreen]="true">
  <ion-header collapse="condense">
    <ion-toolbar>
      <ion-title style="color:dodgerblue;" size="medium">Quiz</ion-title>
    </ion-toolbar>
  </ion-header>

  <ion-refresher slot="fixed" (ionRefresh)="doRefresh($event)">
    <ion-refresher-content
      pullingIcon="chevron-down-circle-outline"
      pullingText="Pull to refresh"
      refreshingSpinner="circles"
      refreshingText="Refreshing...">
    </ion-refresher-content>
  </ion-refresher>

  <div id="container" style="position:relative">
    <ion-row>
      <ion-col>
        <ion-card style="background-color:#95e52e;border: 3px solid white;border-radius: 20px;" routerLink="/level-one">
          <ion-card-content>
            <ion-icon name="lock-open-outline" style="color: white; font-size: 50px"></ion-icon>
            <p>Level 1</p>
            <p>Unlocked</p>
            <ion-icon *ngIf="Score1 >= 3 && Score1 <= 5" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score1 > 5 && Score1 <= 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score1 > 5 && Score1 <= 7"name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score1 > 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score1 > 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score1 > 7"name="star" style="color: #ffff00"></ion-icon>
          </ion-card-content>
        </ion-card>
      </ion-col>

      <ion-col >
        <ion-card *ngIf = "Score1 <= 7" style="background-color:#95e52e;border: 3px solid white;border-radius: 20px;">
          <ion-card-content>
            <ion-icon name="lock-closed-outline" style="color: white; font-size: 50px"></ion-icon>
            <p>Level 2</p>
            <p>Locked</p>
          </ion-card-content>
        </ion-card>

        <ion-card *ngIf = "Score1 > 7" style="background-color:#95e52e;border: 3px solid white;border-radius: 20px;" routerLink="/level-two">
          <ion-card-content>
            <ion-icon name="lock-open-outline" style="color: white; font-size: 50px"></ion-icon>
            <p>Level 2</p>
            <p>Unlocked</p>
            <ion-icon *ngIf="Score2 >= 3 && Score2 <= 5" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score2 > 5 && Score2 <= 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score2 > 5 && Score2 <= 7"name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score2 > 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score2 > 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score2 > 7" name="star" style="color: #ffff00"></ion-icon>
          </ion-card-content>
        </ion-card>
      </ion-col>

    </ion-row>

    <ion-row>
      <ion-col >
        <ion-card *ngIf = "Score2 > 7" style="background-color:#95e52e;border: 3px solid white;border-radius: 20px;" routerLink="/level-three">
          <ion-card-content>
            <ion-icon name="lock-open-outline" style="color: white; font-size: 50px"></ion-icon>
            <p>Level 3</p>
            <p>Unlocked</p>
            <ion-icon *ngIf="Score3 >= 3 && Score3 <= 5" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score3 > 5 && Score3 <= 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score3 > 5 && Score3 <= 7"name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score3 > 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score3 > 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score3 > 7"name="star" style="color: #ffff00"></ion-icon>
          </ion-card-content>
        </ion-card>
        <ion-card *ngIf = "Score2 <= 7" style="background-color:#95e52e;border: 3px solid white;border-radius: 20px;">
          <ion-card-content>
            <ion-icon name="lock-closed-outline" style="color: white; font-size: 50px"></ion-icon>
            <p>Level 3</p>
            <p>Locked</p>
          </ion-card-content>
        </ion-card>
      </ion-col>
      <ion-col >
        <ion-card *ngIf = "Score3 <= 7" style="background-color:#bf7bad;border: 3px solid white;border-radius: 20px;">
          <ion-card-content>
            <ion-icon name="lock-closed-outline" style="color: white; font-size: 50px"></ion-icon>
            <p>Level 4</p>
            <p>Locked</p>
          </ion-card-content>
        </ion-card>
        <ion-card *ngIf = "Score3 > 7" style="background-color:#bf7bad;border: 3px solid white;border-radius: 20px;" routerLink="/level-four">
          <ion-card-content>
            <ion-icon name="lock-open-outline" style="color: white; font-size: 50px"></ion-icon>
            <p>Level 4</p>
            <p>Unlocked</p>
            <ion-icon *ngIf="Score4 >= 3 && Score4 <= 5" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score4 > 5 && Score4 <= 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score4 > 5 && Score4 <= 7"name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score4 > 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score4 > 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score4 > 7"name="star" style="color: #ffff00"></ion-icon>
          </ion-card-content>
        </ion-card>
      </ion-col>
    </ion-row>
    <ion-row>
      <ion-col >
        <ion-card *ngIf = "Score4 <=7" style="background-color:#bf7bad;border: 3px solid white;border-radius: 20px;">
          <ion-card-content>
            <ion-icon name="lock-closed-outline" style="color: white; font-size: 50px"></ion-icon>
            <p>Level 5</p>
            <p>Locked</p>
          </ion-card-content>
        </ion-card>
        <ion-card *ngIf = "Score4 >7" style="background-color:#bf7bad;border: 3px solid white;border-radius: 20px;" routerLink='/level-five'>
          <ion-card-content>
            <ion-icon name="lock-open-outline" style="color: white; font-size: 50px"></ion-icon>
            <p>Level 5</p>
            <p>Unlocked</p>
            <ion-icon *ngIf="Score5 >= 3 && Score5 <= 5" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score5 > 5 && Score5 <= 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score5 > 5 && Score5 <= 7"name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score5 > 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score5 > 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score5 > 7"name="star" style="color: #ffff00"></ion-icon>
          </ion-card-content>
        </ion-card>
      </ion-col>
      <ion-col >
        <ion-card *ngIf = "Score5 <=7" style="background-color:#bf7bad;border: 3px solid white;border-radius: 20px;">
          <ion-card-content>
            <ion-icon name="lock-closed-outline" style="color: white; font-size: 50px"></ion-icon>
            <p>Level 6</p>
            <p>Locked</p>
        
          </ion-card-content>
        </ion-card>
        <ion-card *ngIf = "Score5 >7" style="background-color:#bf7bad;border: 3px solid white;border-radius: 20px;" routerLink='/level-six'>
          <ion-card-content>
            <ion-icon name="lock-open-outline" style="color: white; font-size: 50px"></ion-icon>
            <p>Level 6</p>
            <p>Unlocked</p>
            <ion-icon *ngIf="Score6 >= 3 && totalScore6.sum <= 5" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score6 > 5 && Score6 <= 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score6 > 5 && Score6 <= 7"name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score6 > 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score6 > 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score6 > 7"name="star" style="color: #ffff00"></ion-icon>
          </ion-card-content>
        </ion-card>
      </ion-col>
    </ion-row>
    <ion-row>
      <ion-col >
        <ion-card *ngIf = "Score6 <=7" style="background-color:dodgerblue;border: 3px solid white;border-radius: 20px;">
          <ion-card-content>
            <ion-icon name="lock-closed-outline" style="color: white; font-size: 50px"></ion-icon>
            <p>Level 7</p>
            <p>Locked</p>
      
          </ion-card-content>
        </ion-card>
        <ion-card *ngIf = "Score6 >7" style="background-color:dodgerblue;border: 3px solid white;border-radius: 20px;" routerLink="/level-seven">
          <ion-card-content>
            <ion-icon name="lock-open-outline" style="color: white; font-size: 50px"></ion-icon>
            <p>Level 7</p>
            <p>Unlocked</p>
            <ion-icon *ngIf="Score7 >= 3 && Score7 <= 5" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score7 > 5 && Score7 <= 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score7 > 5 && Score7 <= 7"name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score7 > 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score7 > 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score7 > 7"name="star" style="color: #ffff00"></ion-icon>
          </ion-card-content>
        </ion-card>
      </ion-col>
      <ion-col >
        <ion-card *ngIf = "Score7 <=7" style="background-color:dodgerblue;border: 3px solid white;border-radius: 20px;">
          <ion-card-content>
            <ion-icon name="lock-closed-outline" style="color: white; font-size: 50px"></ion-icon>
            <p>Level 8</p>
            <p>Locked</p>
          
          </ion-card-content>
        </ion-card>
        <ion-card *ngIf = "Score7 > 7" style="background-color:dodgerblue;border: 3px solid white;border-radius: 20px;" routerLink="/level-eight">
          <ion-card-content>
            <ion-icon name="lock-open-outline" style="color: white; font-size: 50px"></ion-icon>
            <p>Level 8</p>
            <p>Unlocked</p>
            <ion-icon *ngIf="Score8 >= 3 && Score8 <= 5" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score8 > 5 && Score8 <= 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score8 > 5 && Score8 <= 7"name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score8 > 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score8 > 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score8 > 7"name="star" style="color: #ffff00"></ion-icon>
          </ion-card-content>
        </ion-card>
      </ion-col>
    </ion-row>
    <ion-row>
      <ion-col >
        <ion-card *ngIf = "Score8 <=7" style="background-color:dodgerblue;border: 3px solid white;border-radius: 20px;">
          <ion-card-content>
            <ion-icon name="lock-closed-outline" style="color: white; font-size: 50px"></ion-icon>
            <p>Level 9</p>
            <p>Locked</p>
           
          </ion-card-content>
        </ion-card>
        <ion-card *ngIf = "Score8 >7"  style="background-color:dodgerblue;border: 3px solid white;border-radius: 20px;" routerLink="/level-nine">
          <ion-card-content>
            <ion-icon name="lock-open-outline" style="color: white; font-size: 50px"></ion-icon>
            <p>Level 9</p>
            <p>Unlocked</p>
            <ion-icon *ngIf="Score9 >= 3 && Score9 <= 5" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score9 > 5 && Score9 <= 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score9 > 5 && Score9 <= 7"name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score9 > 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score9 > 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score9 > 7"name="star" style="color: #ffff00"></ion-icon>
          </ion-card-content>
        </ion-card>
      </ion-col>
      <ion-col >
        <ion-card *ngIf = "Score9 <=7" style="background-color:red;border: 3px solid white;border-radius: 20px;">
          <ion-card-content>
            <ion-icon name="lock-closed-outline" style="color: white; font-size: 50px"></ion-icon>
            <p>Level 10</p>
            <p>Locked</p>
          
          </ion-card-content>
        </ion-card>
        <ion-card *ngIf = "Score9 >7" style="background-color:red;border: 3px solid white;border-radius: 20px;" routerLink="/level-ten">
          <ion-card-content>
            <ion-icon name="lock-open-outline" style="color: white; font-size: 50px"></ion-icon>
            <p>Level 10</p>
            <p>Unlocked</p>
            <ion-icon *ngIf="Score10 >= 3 && Score10 <= 5" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score10 > 5 && Score10 <= 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score10 > 5 && Score10 <= 7"name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score10 > 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score10 > 7" name="star" style="color: #ffff00"></ion-icon>
            <ion-icon *ngIf="Score10 > 7"name="star" style="color: #ffff00"></ion-icon>
          </ion-card-content>
        </ion-card>
      </ion-col>
    </ion-row>
  </div>

</ion-content>

Below is the .ts file ;

import { Component } from '@angular/core';
import {SoundProviderService} from '../sound-provider.service';
import { AlertController } from '@ionic/angular';
import { DatabaseService, scoVar, sum } from 'src/app/services/database.service';
import { ToastController } from '@ionic/angular';
import {NavController} from '@ionic/angular';

@Component({
  selector: 'app-tab2',
  templateUrl: 'tab2.page.html',
  styleUrls: ['tab2.page.scss']
})

export class Tab2Page {

  scoInfo: scoVar[] = [];
  public totalScore1: sum;
  public totalScore2: sum;
  public totalScore3: sum;
  public totalScore4: sum;
  public totalScore5: sum;
  public totalScore6: sum;
  public totalScore7: sum;
  public totalScore8: sum;
  public totalScore9: sum;
  public totalScore10: sum;

  Score1: number;
  Score2: number;
  Score3: number;
  Score4: number;
  Score5: number;
  Score6: number;
  Score7: number;
  Score8: number;
  Score9: number;
  Score10: number;

  constructor(public navCtrl: NavController, public myService: SoundProviderService, public alertController: AlertController, private db: DatabaseService, public toast: ToastController) {
  }

  ngOnInit() {

    this.db.getDatabaseState().subscribe(rdy => {
      if (rdy) {  
        this.db.getScos().subscribe(score => {
          this.scoInfo = score;
          // console.log(this.scoInfo);
        });
        //clevel1
        this.db.getSum(1).then(data => {
          this.totalScore1 = data;
          console.log(this.totalScore1.sum);
          this.Score1 = this.totalScore1.sum;
        });
        //clevel2
        this.db.getSum(2).then(data => {
          this.totalScore2 = data;
          console.log(this.totalScore2.sum);
          this.Score2 = this.totalScore2.sum;
        });
        //clevel3
        this.db.getSum(3).then(data => {
          this.totalScore3 = data;
          console.log(this.totalScore3.sum);
          this.Score3 = this.totalScore3.sum;
        });
        //clevel4
        this.db.getSum(4).then(data => {
          this.totalScore4 = data;
          console.log(this.totalScore4.sum);
          this.Score4 = this.totalScore4.sum;
        });
        //clevel5
        this.db.getSum(5).then(data => {
          this.totalScore5 = data;
          console.log(this.totalScore5.sum);
          this.Score5 = this.totalScore5.sum;
        });
        //clevel6
        this.db.getSum(6).then(data => {
          this.totalScore6 = data;
          console.log(this.totalScore6.sum);
          this.Score6 = this.totalScore6.sum;
        });
        //clevel7
        this.db.getSum(7).then(data => {
          this.totalScore7 = data;
          console.log(this.totalScore7.sum);
          this.Score7 = this.totalScore7.sum;
        });
        //clevel8
        this.db.getSum(8).then(data => {
          this.totalScore8 = data;
          console.log(this.totalScore8.sum);
          this.Score8 = this.totalScore8.sum;
        });
        //clevel9
        this.db.getSum(9).then(data => {
          this.totalScore9 = data;
          console.log(this.totalScore9.sum);
          this.Score9 = this.totalScore9.sum;
        });
        //clevel10
        this.db.getSum(10).then(data => {
          this.totalScore10 = data;
          console.log(this.totalScore10.sum);
          this.Score10 = this.totalScore10.sum;
        });
      }
    });
  }

  doRefresh(event) {
    console.log('Begin async operation');

    setTimeout(() => {
      console.log('Async operation has ended');
      event.target.complete();
    }, 2000);
    
    // location.reload();     //// this serves the purpose by reloading the entire app but its not what i want

    this.navCtrl.navigateRoot('/tabs/tab2');  //// I tried this but not able to update 
  }

}

For more reference below is the git repo for more info.
https://github.com/KarmaTensel/DDC_App

It is a bit lengthy and my codes are messy but I would be really grateful for any help??! Thank you.

Wow.

I’m at a bit of a loss for words. You obviously put in a ton of work on this, and I don’t know how to best say this diplomatically, but…I would structure things very differently here in general, because there is a lot of boilerplate.

What I would have done instead is to define interfaces for Question, Quiz, &c, and then structure the actual quizzes and questions as JSON assets. That way you only have to have one single QuizPage that can handle any properly-formatted quiz asset. Designing it that way achieves two hugely important maintenance goals:

  1. Adding questions and new quizzes can be done simply by adding assets - absolutely zero code modification required. Now, adding a new quiz is a major undertaking, involving changes in SQL and new pages.
  2. Any interface improvements immediately propagate to all quizzes. The way it is now, you would have to change eleventy kajillion hardcoded quiz pages whenever you wanted to change anything about the interface.

Updating a single answer to a single question also necessitates a complete reload of every score of every question of every quiz, the way things are written. I would expect that to negate any possible performance benefit of using SQLite at all (although one could argue that SQLite isn’t really needed or wanted here anyway).

But you didn’t come here asking for design advice, and I’m basically advising totally rewriting the app, which I expect you are very unlikely to want to hear.

So, if you’re looking to change things as little as possible, at a very minimum you need to rearchitect getSum, and make it return an Observable (that actually updates when necessitated) instead of a Promise. Promises are for one-shot operations, whereas these sums are long-lived, periodically changing beasts.

2 Likes

Thank you for the response and tips on design. All of the things you mentioned about the design must have been an oversight since I am still exploring it.

As you suggested using Observable instead of Promise, I looked up how to implement observable but I am not very confident implementing observable, especially in my case, where I need to return getSum as an observable. Could you help me with that?

I would suggest reading the Angular documentation about Observables and general RxJS documentation, and again keeping in mind that what I would really do here is to get SQL out of the loop entirely, given that you already have a Promise, you can make either a BehaviorSubject (if you can always guarantee that there is some value, or if “no value” becomes possible at runtime - this should not be the case in your app, as I understand it) or a ReplaySubject of stack size 1, expose that as your Observable, and then next at it every time you calculate a new total score.

1 Like