feat(angular): add tabs events (#17125)

* feat(angular): add tabs events

* lint
This commit is contained in:
Manu MA
2019-01-15 22:07:53 +01:00
committed by GitHub
parent 0693c887f9
commit 6929bb817c
7 changed files with 72 additions and 26 deletions

View File

@ -25,6 +25,7 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
tabsPrefix: string | undefined;
@Output() stackEvents = new EventEmitter<any>();
@Output('activate') activateEvents = new EventEmitter<any>();
@Output('deactivate') deactivateEvents = new EventEmitter<any>();
@ -173,9 +174,9 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
}
this.activatedView = enteringView;
this.stackCtrl.setActive(enteringView).then(() => {
this.stackCtrl.setActive(enteringView).then(data => {
this.activateEvents.emit(cmpRef.instance);
emitEvent(this.nativeEl, enteringView!);
this.stackEvents.emit(data);
});
}
@ -197,15 +198,6 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
}
}
function emitEvent(el: HTMLElement, view: RouteView) {
const ev = new CustomEvent('ionRouterOutletActivated', {
bubbles: true,
cancelable: true,
detail: { view }
});
el.dispatchEvent(ev);
}
class OutletInjector implements Injector {
constructor(
private route: ActivatedRoute,

View File

@ -1,17 +1,17 @@
import { Component, ContentChild, HostListener, ViewChild } from '@angular/core';
import { Component, ContentChild, EventEmitter, HostListener, Output, ViewChild } from '@angular/core';
import { NavController } from '../../providers/nav-controller';
import { IonTabBar } from '../proxies';
import { IonRouterOutlet } from './ion-router-outlet';
import { RouteView } from './stack-utils';
import { StackEvent } from './stack-utils';
@Component({
selector: 'ion-tabs',
template: `
<ng-content select="[slot=top]"></ng-content>
<div class="tabs-inner">
<ion-router-outlet #outlet tabs="true"></ion-router-outlet>
<ion-router-outlet #outlet tabs="true" (stackEvents)="onPageSelected($event)"></ion-router-outlet>
</div>
<ng-content></ng-content>`,
styles: [`
@ -45,6 +45,9 @@ export class IonTabs {
@ViewChild('outlet', { read: IonRouterOutlet }) outlet: IonRouterOutlet;
@ContentChild(IonTabBar) tabBar: IonTabBar | undefined;
@Output() ionTabsWillChange = new EventEmitter<{tab: string}>();
@Output() ionTabsDidChange = new EventEmitter<{tab: string}>();
constructor(
private navCtrl: NavController,
) {}
@ -52,10 +55,14 @@ export class IonTabs {
/**
* @internal
*/
@HostListener('ionRouterOutletActivated', ['$event.detail'])
onPageSelected(detail: {view: RouteView}) {
if (this.tabBar) {
this.tabBar.selectedTab = detail.view.stackId;
onPageSelected(detail: StackEvent) {
const stackId = detail.enteringView.stackId;
if (detail.tabSwitch && stackId !== undefined) {
if (this.tabBar) {
this.tabBar.selectedTab = stackId;
}
this.ionTabsWillChange.emit({ tab: stackId });
this.ionTabsDidChange.emit({ tab: stackId });
}
}

View File

@ -5,7 +5,7 @@ import { RouterDirection } from '@ionic/core';
import { bindLifecycleEvents } from '../../providers/angular-delegate';
import { NavController } from '../../providers/nav-controller';
import { RouteView, computeStackId, destroyView, getUrl, insertView, isTabSwitch, toSegments } from './stack-utils';
import { RouteView, StackEvent, computeStackId, destroyView, getUrl, insertView, isTabSwitch, toSegments } from './stack-utils';
export class StackController {
@ -50,16 +50,23 @@ export class StackController {
return view;
}
async setActive(enteringView: RouteView) {
async setActive(enteringView: RouteView): Promise<StackEvent> {
let { direction, animation } = this.navCtrl.consumeTransition();
const leavingView = this.activeView;
if (isTabSwitch(enteringView, leavingView)) {
const tabSwitch = isTabSwitch(enteringView, leavingView);
if (tabSwitch) {
direction = 'back';
animation = undefined;
}
this.insertView(enteringView, direction);
await this.transition(enteringView, leavingView, animation, this.canGoBack(1), false);
requestAnimationFrame(() => this.cleanup());
await this.cleanupAsync();
return {
enteringView,
direction,
animation,
tabSwitch
};
}
canGoBack(deep: number, stackId = this.getActiveStackId()): boolean {
@ -122,6 +129,15 @@ export class StackController {
this.views = insertView(this.views, enteringView, direction);
}
private cleanupAsync() {
return new Promise(resolve => {
requestAnimationFrame(() => {
this.cleanup();
resolve();
});
});
}
private cleanup() {
const activeRoute = this.activeView;
const views = this.views;

View File

@ -1,6 +1,6 @@
import { ComponentRef } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { RouterDirection } from '@ionic/core';
import { NavDirection, RouterDirection } from '@ionic/core';
export function insertView(views: RouteView[], view: RouteView, direction: RouterDirection) {
if (direction === 'root') {
@ -44,7 +44,7 @@ export function getUrl(router: Router, activatedRoute: ActivatedRoute) {
export function isTabSwitch(enteringView: RouteView, leavingView: RouteView | undefined) {
if (!leavingView) {
return false;
return true;
}
return enteringView.stackId !== leavingView.stackId;
}
@ -80,6 +80,13 @@ export function destroyView(view: RouteView | undefined) {
}
}
export interface StackEvent {
enteringView: RouteView;
direction: RouterDirection;
animation: NavDirection | undefined;
tabSwitch: boolean;
}
export interface RouteView {
id: number;
url: string;