Navigate to Page in specific Tab

I need to navigate to a page but have it open in a specific tab. I know how to select the tab and am doing so with this:

this.app.getRootNav().getActiveChildNav().select(3);

but this shows the root component for that tab. I need to either change the root component after I change tabs or push the page after I switch tabs.

2 Likes

Hey @adibbz, did you figure this out? I need to do the same, and have searched high and low for a solution but found nothing so far that works :cry:

3 Likes

Just a thought: How about you emit an event, in the tab you handle that event and then go somewhere. (No idea if this works, just trying to give you something to try)

1 Like

Perhaps relevant.

Thanks for the quick reply @Sujan12 (I’m working on a test to try and do what you describe…still trying to learn how) and the suggestion @rapropos, which is indeed somewhat relevant, but not quite what I’m looking for. The best way I can describe is via an illustration of a very basic example:

Say I have a Dashboard tab, and a Posts tab, and from the Posts tab you can add a new Post by clicking the “Add +” in the Posts header. I also want to add a tab via a FAB button on the Dashboard, like so:

What I can’t figure out how to do, is to go directly to the “Add a Post” page and also select the appropriate “Posts” tab at the same time.

You could use ion-segment instead of ion-tab, and both buttons expose the same hidden content with an ngIf. Then everything is on one page, no navigation needed. The costs are: ngIf can get checked a lot, and you might need two copies of the New Post stuff (which I would separate out as a component).

Interesting idea :wink:

@Sujan12 I’ve tried doing what you suggested, using an Observable, but oddly enough this just isn’t working. The selectedIndex attribute doesn’t seem to have any effect, even though the index variable that I’m setting it to definitely changes. It’s the strangest thing :frowning: I’m considering opening an ionic-team/ionic issue, as it seems…odd.

I’ve set up an example repo, if you have a chance to take a look?

(the tab state is in /src/state/TabStore, and the index changes when you click on the “new post” button from the FAB on the 1st tab - home page)

And here is my ionic info:

% ionic info

global packages:

    @ionic/cli-utils : 1.4.0
    Ionic CLI        : 3.4.0

local packages:

    @ionic/app-scripts              : 1.3.12
    @ionic/cli-plugin-ionic-angular : 1.3.1
    Ionic Framework                 : ionic-angular 3.5.0

System:

    Node       : v6.9.2
    OS         : macOS Sierra
    Xcode      : Xcode 8.3.3 Build version 8E3004b
    ios-deploy : 1.8.2
    ios-sim    : 5.0.3
    npm        : 3.10.9

Pulling my hair out!

A few comments:

  1. Most likely source of your problem is use of asObservable, which is an rxjs 4 extension, and Angular is now using rxjs 5.

  2. I couldn’t find selectedIndex. Am I blind, or is that a previous name of your BehaviorSubject/Observable?

  3. Your Node and npm are out of date. I’d suggest you update to the Node LTS and if for some reason you don’t want to move to npm 4 (or 5), be sure to install 3.10.10, because it fixes bugs in 3.10.9. That’s the last version 3.

  4. Typescript public variables turn into global variables as you may know, so use of them in your service fights against the principle of DI. I’d suggest you force access to index through a method. That might be the issue right there, though it’s probably the rxjs 4. But I’ve got BehaviorSubjects in my code, and they next just fine in Ionic 3.5.

Thanks so much for the feedback! Much appreciated for taking the time.

  1. Most likely source of your problem is use of asObservable, which is an rxjs 4 extension, and Angular is now using rxjs 5.

I’ll try to figure out the newer way of doing this (maybe Rx.Subject?). I’m completely new to rxjs , so have a lot of catching up to do.

  1. I couldn’t find selectedIndex. Am I blind, or is that a previous name of your BehaviorSubject/Observable?

Do you mean where the attribute is set on <ion-tabs>? It’s in the tabs.html.

  1. Your Node and npm are out of date. I’d suggest you update to the Node LTS and if for some reason you don’t want to move to npm 4 (or 5), be sure to install 3.10.10, because it fixes bugs in 3.10.9. That’s the last version 3.

I’ve updated node to v6.11.0 (LTS), and npm to 5.0.4, but this seems to make no difference.

  1. Typescript public variables turn into global variables as you may know, so use of them in your service fights against the principle of DI. I’d suggest you force access to index through a method. That might be the issue right there, though it’s probably the rxjs 4. But I’ve got BehaviorSubjects in my code, and they next just fine in Ionic 3.5.

Ah, being new to typescript as well, that was an oversight on my part. So I removed the public visibility, and moved access to it into a getIndex method:

// => src/pages/tabs/tabs.ts
constructor(private tabStore: TabStore) {
  this.tabStore.index.subscribe((value) => {
    console.log('index', value)
    this.index = value;
  });
}

getIndex() {
  return this.index;
}

// => src/pages/tabs/tabs.html
<ion-tabs selectedIndex="getIndex()">
  <ion-tab [root]="tab1Root" tabTitle="Home" tabIcon="home"></ion-tab>
  <ion-item>index: {{getIndex()}}</ion-item>
  <ion-tab [root]="tab2Root" tabTitle="Posts" tabIcon="list"></ion-tab>
</ion-tabs>

The <ion-item> reports the correct index value, but the selected tab still doesn’t change :confused:

In order to have a bound property be evaluated instead of treated as a string literal, you must wrap it in square brackets: [selectedIndex].

Good catch! I’d accidentally removed the property binding when I was testing around. Though even with it correct now, it still unfortunately doesn’t make a difference.

Two main possibilities: either getIndex() is not updating, or the template is not hearing it. My guess is this is a change detection issue, since the template isn’t exactly the current open page, and Angular change is not the same as ionChange. But I’ve never programmed seriously with tabs so I don’t know. But if your getIndex is working correctly, then what I’d try next is to call ChangeDetectorRef.detectChanges() each time I nexted the BehaviorSubject, to see if that forced ion-tabs to update selectedIndex.

Thanks @AaronSterling, what you’re describing with regard to change detection makes sense, however it seems to make no difference when I use ChangeDetectorRef.detectChanges() after updating the index.

I’ve gone ahead and added an issue at ionic-team/ionic for this, seems like a bug.

Well now I’m really curious! Ok one more suggestion and I’m officially out of ideas. Next the BehaviorSubject, then call ApplicationRef.tick(). That’s expensive, so I didn’t mention it before, but if it doesn’t work, then yeah, it sure feels like a bug. Thanks for an interesting problem!

That didn’t work either, hah! It’s a super curious problem indeed – thanks so much for taking the time to look at this though, good ideas!

Don’t know if this will help anybody here but after weeks, I was able to get this to work for me.

From any other page/component I use the below code to select the tab I want.

let nav = this.app.getRootNav(); 
nav.setRoot(TabsPage, {tabIndex: 2});

And in my tabs.ts I have:

this.mySelectedIndex = navParams.data.tabIndex || 0;

And in my tabs.html template:

<ion-tabs [selectedIndex]="mySelectedIndex" #myTabs (ionChange)="doChange($event)">
7 Likes

I really don’t like this idiom. I call it “mystery action at a distance”. It makes app code much easier to understand if all action is localized as much as absolutely possible. That means that all interaction with the root nav stack should be done inside the app component, not randomly all over the app. I have not yet come across a defensible use case for injecting App anywhere.

What is the alternative @rapropos? How would you do what @adibbz suggested?

That’s a hard question to answer without knowing more about the intended UX of the app. In general, I believe that most attempts to do “go to tab X out of random page Y” are disruptive and indicate that perhaps tabs are a bad fit for the app. The one situation that I have encountered that makes sense, although it is not specific to tabs, is with user authentication going stale. Whereever we are in the app, if we have lost authentication, we need to go to the login page. As I expect you’re tired of hearing, the way I handle that is with a subscription in the app component that swaps out the root page whenever a deauthentication event (either user-initiated via logout or organic via other means) occurs. This is localized to the app component, and thus can be tested there.