Capturing ion-tab click on active tab event

@markhardling. this seems to be the solution everyone is looking for. worked for me! thanks

Would you give an example… how to add ionSelected() to the component??

hi guys, I got a hacked solution, hope help someone:

export class TabsPage {
  tabHome: any = HomePage;   
  selectedIndex: number = 0;
  tabHomeClickEvent: any; //for home tab click event
  constructor(public navCtrl: NavController, public events: Events) {
    let that = this;
    this.tabHomeClickEvent = function(e) {
      if(0 == that.selectedIndex){
        //tab home be clicked!
        //do some thing
      }
    }
  }

  // <ion-tabs (ionChange)="tabChange($event)">
  tabChange(tab: Tab){
    this.selectedIndex = tab.index;
    console.log(this.selectedIndex);
    //index equals 0/other to add/remove tab home click event 
    if(0 == this.selectedIndex){
      this.tabHomeAddClickEvent();
    }
    else{
      this.tabHomeRemoveClickEvent();
    }
  }


  //ion-md-home: <ion-tab home [root]="tabHome" tabTitle="Home" tabIcon="md-home"></ion-tab>
  private tabHomeAddClickEvent(): void {

    let that = this;
    let tabHomeIcon = document.getElementsByClassName('ion-md-home');
    if(tabHomeIcon.length == 1){
      tabHomeIcon[0].addEventListener('click', that.tabHomeClickEvent, true)
    }

  }

  private tabHomeRemoveClickEvent(): void {
 
    let that = this;
    let tabHomeIcon = document.getElementsByClassName('ion-md-home');
    if(tabHomeIcon.length == 1){
      tabHomeIcon[0].removeEventListener('click',that.tabHomeClickEvent , true);
    }
 
  }  


}

3 Likes

I’m using this solution:

tabs.html

<ion-tabs #mainTabs (tap)="tapped()">
  <ion-tab [root]="tab1Root" tabTitle="Home" tabIcon="paper"></ion-tab>
  <ion-tab [root]="tab2Root" tabTitle="About" tabIcon="information-circle"></ion-tab>
  <ion-tab [root]="tab3Root" tabTitle="Contact" tabIcon="contacts"></ion-tab>
</ion-tabs>

tabs.ts

@ViewChild('mainTabs') mainTabs: Tabs;

constructor(public nav:NavController, public events: Events ) {}

// This will be executed before ionChange event
public tapped() {
    this.events.publish('home:scrollToTop', Date.now() );
}

home.ts

[...]
@ViewChild(Content) content: Content;

constructor(public app: App, public nav: NavController, public events: Events, private logic:StpLogicService) {
    // NOTE: This will be executed only when home is already the active/current tab
    events.subscribe('home:scrollToTop', (time) => {
      console.log('home:scrollToTop', 'at', time);
      this.content.scrollToTop();
    });
}

The effect is: Homepage si scrolled to top only when already displayed.

8 Likes

Does anyone have another solution for this issue? When I try to use BLaCkSMiTH77 solution, my content scrolls also when I scroll down to a button and push from there a new View on the Viewstack which should not happen! The other solutions does not work for me but I dont know how to use ionSelected() as markharding replied.

Thanks guys.

ionSelected() must be implemented in the called component. Thanks @markharding.
@okbong here is an example how it works:

tabs.html

    <ion-tabs>
        <ion-tab [root]="tab1"></ion-tab>
        <ion-tab [root]="tab2"></ion-tab>
    </ion-tabs>

tabs.ts (straight forward)

export class TabsPage {
  tab1: any = HomePage;
  tab2: any = OtherPage;

  constructor() {
  }
}

home.ts

export class HomePage {
 
  constructor() {
  }

  ionSelected() {
    console.log("Home Page has been selected");
    // do your stuff here
  }
}}
20 Likes

This solved a slightly different problem for me.

I noticed that when I click an already selected tab, it gets destroyed and recreated again. What’s even worse, the “rootParams” specified in the Tabs are not passed to the page when recreating. Do you think this is a bug?

When I add the ionSelected() method, the tab page won’t be recreated so that solved my problem. Is this method documented somewhere? I couldn’t find it anywhere else than here.

It seems it is best to add an empty ionSelected to every tab page to prevent recreating the page and to avoid unexpected bugs. It’s a bit strange it isn’t documented properly anywhere.

I think you’re refering to the discussion over here: Tab reloading while double click the tab

which resulted in a pull request, which you can track over here:

Right, that’s it. Thanks!

Thanks @psalchow that was exactly I searched for :slight_smile: You helped me a lot.

Thank you for your code.

Is there any documentation on ionSelected()?

Well I would like to know more about this method and about possible similar methods!

Worked fine for me. It will execute if you click on current active page. Nice. Thanks alot

Thanks @psalchow his is the trick I’ve been searching for…

Thanks a lot. It works perfectly

Awesome!! Thanks a lot :kissing_heart:

Thanks, I resolved my issue.

I needed a long press on a tab button. Here is what I came up with, hope it helps someone:

...
<ion-tab #helpTab tabTitle="HELP" tabIcon="help"></ion-tab>
...
import { Component, ViewChild, AfterViewInit } from '@angular/core';
import { NavParams, Tab, TabButton } from 'ionic-angular';
import { Observable } from 'rxjs/Observable';

@Component({
  templateUrl: 'tabs.html'
})
export class TabsPage implements AfterViewInit {
  private longpressTimeOut:any;
  private initialTouchX:number;
  private initialTouchY:number;
  @ViewChild("helpTab") helpTab: Tab;

  private initiateTimer() {
    if (this.longpressTimeOut) {
      clearTimeout(this.longpressTimeOut);
    }
    this.longpressTimeOut = setTimeout(() => {
      console.log("Longpress Triggered!")
    }, 5000);
  }

  ngAfterViewInit(): void {
    console.log("helpTab", this.helpTab)

    let tabButton: TabButton = this.helpTab.btn

    Observable.fromEvent(tabButton.getNativeElement(), 'touchstart').subscribe(
      (touchEvent: TouchEvent) => {
        console.log("touchstart")
        this.initialTouchX = touchEvent.changedTouches[0].pageX;
        this.initialTouchY = touchEvent.changedTouches[0].pageY;
        this.initiateTimer();
      }
    )

    Observable.fromEvent(tabButton.getNativeElement(), 'touchmove').subscribe(
      (touchEvent: TouchEvent) => {
        if ((Math.abs(touchEvent.changedTouches[0].pageX - this.initialTouchX) > 20)
          || (Math.abs(touchEvent.changedTouches[0].pageY - this.initialTouchY) > 20)
        ) {
          console.log("touchmove outside of tollerance... canceling longpress");
          if (this.longpressTimeOut) {
            clearTimeout(this.longpressTimeOut);
          }
        }
      }
    )

    Observable.fromEvent(tabButton.getNativeElement(), 'touchend').subscribe(
      (touchEvent: TouchEvent) => {
        console.log("touchend")
        if (this.longpressTimeOut) {
          clearTimeout(this.longpressTimeOut);
        }
      }
    )
  }
}

1 Like

Hi all, I have an answer to satisfy all of you I think.

The easiest way to do what is wanted by the OP (and also all the other event has mentionned by the comments) can be done using event binding.

In your tabs.ts file (or the file used to generate the tabs that will hold your pages), you can use an ngAfterViewInit() function that triggers once the page has loaded, and then bind all the buttons to the tabs HTML element and then do the appropriate action. You can bind them to those tags since they all have unique IDs associated with them.

Here’s how I did it:

  // Once the view is done loading (this is triggered automatically)
  ngAfterViewInit(){

    // Get the element by the id 'tab-0-0' attributed by the Ionic team for the first button
    document.getElementById('tab-t0-0').addEventListener('click', event => {

      // Execute your code here when the first button is clicked

    });

    // Get the element by the id 'tab-0-1' attributed by the Ionic team for the second button
    document.getElementById('tab-t0-1').addEventListener('click', event => {

      // Execute your code here when the second button is clicked

    });
    // Get the element by the id 'tab-0-2' attributed by the Ionic team for the third button
    document.getElementById('tab-t0-2').addEventListener('click', event => {

      // Execute your code here when the third button is clicked

    });

    // You can add as many as you want from here, just remember to increment the ID
  }

If you want, you can change the click event to be any other event (maybe hold or something similar has mentionned by some people).

Cheers! :slight_smile:

1 Like

[DEPRECATED (with new solution) ]

If you close and reopen the Tabs page, a new ID will be generated for the new Tabs page if not destroyed properly.

The name will go from “tab-t0-1” to “tab-t1-1”. So you need to ensure that you generate the subscription for several different IDs every time you trigger the ngAfterViewInit().

I iterated through the different IDs until an ID was not undefined and then I triggered the subscription with the existing IDs.

Hope it helps (again)! :slight_smile: