Sorakthun Ly Sorakthun Ly - 3 months ago 106
TypeScript Question

Change selected Tab after CRUD operation - Ionic2

The app is a simple workout entry tool. It does basic API call for CRUD operations. App Display

I can't reload the Workout Tab after a new entry is created and stored to the database. I was able to manipulate NavController to set root for it to display the updated data but it's only under the Add Workout tab. Workouts updated in Add Workout tab When I tab back to Workout tab. It displays the result as the first image attached.

I presume this is because the constructor and NgOnInit are initialized only once. How can I get around this?

This is the code for the Workout tab.

export class WorkoutPage {
navCtrl;
workoutService;
workouts;

static get parameters() {
return [NavController, WorkoutService];
}

constructor(navCtrl, workoutService) {
this.navCtrl = navCtrl;
this.workoutService = workoutService;
this.workoutService.getWorkouts().subscribe(workouts => {
this.workouts = workouts;
})
}

ngOnInit() {
this.workoutService.getWorkouts().subscribe(workouts => {
this.workouts = workouts;
})
}

workoutSelected(event, workout) {
this.navCtrl.push(WorkoutdetailPage, {
workout: workout
})
}
}


This is how I do setRoot after new entry is added to the database.

onSubmit() {
var workout = {
title: this.title,
note: this.note,
type: this.type
}

this.workoutService.addWorkout(workout)
.subscribe(data => {
this.result = data;
}, err => console.log(err),
() => console.log("Workout added"));

this.navCtrl.setRoot(WorkoutPage);
}


I really need a way to refresh data on the Workout page. Your help is very much appreciated.

Answer

You can do that by using an observable

EDIT: I've edited the answer because instead of using the observable for syncing both components, you need to use the observable just to be able to change the selected tab once the new item is added. You can find a demo and the explanation of how to do this in the new documentation section.

Please take a look at this working plunker. Since each tab has its own nav history, you can't just use the setRoot() method inside one tab, because that's going to set the new page as the root of that tab instead of returning the user to the other tab.

So the idea is to use an observable to allow one of the child components (the page that inserts the new item) to tell the parent component (the page that contains both tabs) that it should change the selected tab (in this case, the page that shows the list of items).

TabService

import {Injectable} from '@angular/core';
import {Observable} from 'rxjs/Observable';

@Injectable()
export class TabService { 

  private tabChangeObserver: any;
  public tabChange: any;

  constructor(){
    this.tabChangeObserver = null;
    this.tabChange = Observable.create(observer => {
        this.tabChangeObserver = observer;
    });
  }

  public changeTabInContainerPage(index: number) {
    this.tabChangeObserver.next(index);
  }
}

So basically the TabService only creates an Observable to allow the tabs container to subscribe to it, and also declares the changeTabInContainerPage() method that will be called from the child pages.

In the TabsPage, we only subscribe to the service, and then we change the selected tab with this.tabRef.select(index);

import { Component, ViewChild } from "@angular/core";
import { Page1 } from './page1.ts';
import { Page2 } from './page2.ts';
import { TabService } from 'tabService.ts'; 

@Component({
  templateUrl: 'tabs.html'
})
export class TabsPage {
  @ViewChild('myTabs') tabRef: Tabs;

  tab1Root: any = Page1;
  tab2Root: any = Page2;

  constructor(private tabService: TabService){
    this.tabService.tabChange.subscribe((index) => {
      this.tabRef.select(index);
    });
  }
}

Please notice that we're getting a reference to the Tabs instance by adding #myTabs in the ion-tabs element, and we get it from the component with @ViewChild('myTabs') tabRef: Tabs;

<ion-tabs #myTabs>
  <ion-tab [root]="tab1Root" tabTitle="Tab 1"></ion-tab>
  <ion-tab [root]="tab2Root" tabTitle="Tab 2"></ion-tab>
</ion-tabs>

Then, the only thing left to be done is to just call that method when the new item was added to the list:

    // Add the new item
    this.workoutService.addWorkout(this.newWorkout)
        .subscribe(
          (data) => {

            // Reset the form
            this.newWorkout = '';

            // Change the selected tab
            this.tabService.changeTabInContainerPage(0);
          }, 
          (err) => console.log(err),
          () => console.log("Workout added"));
Comments