mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-16 01:52:19 +08:00
fix(angular): ionTabsWillChange is fired before tab activation (#27991)
Issue number: Resolves #27212 --------- <!-- Please do not submit updates to dependencies unless it fixes an issue. --> <!-- Please try to limit your pull request to one type (bugfix, feature, etc). Submit multiple pull requests if needed. --> ## What is the current behavior? <!-- Please describe the current behavior that you are modifying. --> `ionTabsWillChange` emits _after_ the tab view is activated in the stack. ## What is the new behavior? <!-- Please describe the behavior or changes that are being added by this PR. --> - `ionTabsWillChange` emits _before_ the tab view is activated in the stack. ## Does this introduce a breaking change? - [ ] Yes - [x] No <!-- If this introduces a breaking change, please describe the impact and migration path for existing applications below. --> ## Other information <!-- Any other information that is important to this PR such as screenshots of how the component looks before and after the change. --> Dev-build: `7.2.4-dev.11692040948.1fd0ecd2`
This commit is contained in:
@ -30,7 +30,7 @@ import { Config } from '../../providers/config';
|
||||
import { NavController } from '../../providers/nav-controller';
|
||||
|
||||
import { StackController } from './stack-controller';
|
||||
import { RouteView, getUrl } from './stack-utils';
|
||||
import { RouteView, StackDidChangeEvent, StackWillChangeEvent, getUrl, isTabSwitch } from './stack-utils';
|
||||
|
||||
// TODO(FW-2827): types
|
||||
|
||||
@ -66,7 +66,11 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
*/
|
||||
@Input() name = PRIMARY_OUTLET;
|
||||
|
||||
@Output() stackEvents = new EventEmitter<any>();
|
||||
/** @internal */
|
||||
@Output() stackWillChange = new EventEmitter<StackWillChangeEvent>();
|
||||
/** @internal */
|
||||
@Output() stackDidChange = new EventEmitter<StackDidChangeEvent>();
|
||||
|
||||
// eslint-disable-next-line @angular-eslint/no-output-rename
|
||||
@Output('activate') activateEvents = new EventEmitter<any>();
|
||||
// eslint-disable-next-line @angular-eslint/no-output-rename
|
||||
@ -304,9 +308,16 @@ export class IonRouterOutlet implements OnDestroy, OnInit {
|
||||
*/
|
||||
this.navCtrl.setTopOutlet(this);
|
||||
|
||||
const leavingView = this.stackCtrl.getActiveView();
|
||||
|
||||
this.stackWillChange.emit({
|
||||
enteringView,
|
||||
tabSwitch: isTabSwitch(enteringView, leavingView),
|
||||
});
|
||||
|
||||
this.stackCtrl.setActive(enteringView).then((data) => {
|
||||
this.activateEvents.emit(cmpRef.instance);
|
||||
this.stackEvents.emit(data);
|
||||
this.stackDidChange.emit(data);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -16,14 +16,19 @@ import { NavController } from '../../providers/nav-controller';
|
||||
import { IonTabBar } from '../proxies';
|
||||
|
||||
import { IonRouterOutlet } from './ion-router-outlet';
|
||||
import { StackEvent } from './stack-utils';
|
||||
import { StackDidChangeEvent, StackWillChangeEvent } from './stack-utils';
|
||||
|
||||
@Component({
|
||||
selector: 'ion-tabs',
|
||||
template: `
|
||||
<ng-content select="[slot=top]"></ng-content>
|
||||
<div class="tabs-inner" #tabsInner>
|
||||
<ion-router-outlet #outlet tabs="true" (stackEvents)="onPageSelected($event)"></ion-router-outlet>
|
||||
<ion-router-outlet
|
||||
#outlet
|
||||
tabs="true"
|
||||
(stackWillChange)="onStackWillChange($event)"
|
||||
(stackDidChange)="onStackDidChange($event)"
|
||||
></ion-router-outlet>
|
||||
</div>
|
||||
<ng-content></ng-content>
|
||||
`,
|
||||
@ -62,7 +67,13 @@ export class IonTabs implements AfterContentInit, AfterContentChecked {
|
||||
@ContentChild(IonTabBar, { static: false }) tabBar: IonTabBar | undefined;
|
||||
@ContentChildren(IonTabBar) tabBars: QueryList<IonTabBar>;
|
||||
|
||||
/**
|
||||
* Emitted before the tab view is changed.
|
||||
*/
|
||||
@Output() ionTabsWillChange = new EventEmitter<{ tab: string }>();
|
||||
/**
|
||||
* Emitted after the tab view is changed.
|
||||
*/
|
||||
@Output() ionTabsDidChange = new EventEmitter<{ tab: string }>();
|
||||
|
||||
private tabBarSlot = 'bottom';
|
||||
@ -80,10 +91,19 @@ export class IonTabs implements AfterContentInit, AfterContentChecked {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
onPageSelected(detail: StackEvent): void {
|
||||
const stackId = detail.enteringView.stackId;
|
||||
if (detail.tabSwitch && stackId !== undefined) {
|
||||
onStackWillChange({ enteringView, tabSwitch }: StackWillChangeEvent): void {
|
||||
const stackId = enteringView.stackId;
|
||||
if (tabSwitch && stackId !== undefined) {
|
||||
this.ionTabsWillChange.emit({ tab: stackId });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
onStackDidChange({ enteringView, tabSwitch }: StackDidChangeEvent): void {
|
||||
const stackId = enteringView.stackId;
|
||||
if (tabSwitch && stackId !== undefined) {
|
||||
if (this.tabBar) {
|
||||
this.tabBar.selectedTab = stackId;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import { NavController } from '../../providers/nav-controller';
|
||||
|
||||
import {
|
||||
RouteView,
|
||||
StackEvent,
|
||||
StackDidChangeEvent,
|
||||
computeStackId,
|
||||
destroyView,
|
||||
getUrl,
|
||||
@ -61,7 +61,7 @@ export class StackController {
|
||||
return view;
|
||||
}
|
||||
|
||||
setActive(enteringView: RouteView): Promise<StackEvent> {
|
||||
setActive(enteringView: RouteView): Promise<StackDidChangeEvent> {
|
||||
const consumeResult = this.navCtrl.consumeTransition();
|
||||
let { direction, animation, animationBuilder } = consumeResult;
|
||||
const leavingView = this.activeView;
|
||||
@ -224,6 +224,13 @@ export class StackController {
|
||||
return this.activeView ? this.activeView.stackId : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
getActiveView(): RouteView | undefined {
|
||||
return this.activeView;
|
||||
}
|
||||
|
||||
hasRunningTask(): boolean {
|
||||
return this.runningTask !== undefined;
|
||||
}
|
||||
|
@ -79,10 +79,23 @@ export const destroyView = (view: RouteView | undefined): void => {
|
||||
}
|
||||
};
|
||||
|
||||
export interface StackEvent {
|
||||
export interface StackWillChangeEvent {
|
||||
enteringView: RouteView;
|
||||
/**
|
||||
* `true` if the event is trigged as a result of a switch
|
||||
* between tab navigation stacks.
|
||||
*/
|
||||
tabSwitch: boolean;
|
||||
}
|
||||
|
||||
export interface StackDidChangeEvent {
|
||||
enteringView: RouteView;
|
||||
direction: RouterDirection;
|
||||
animation: NavDirection | undefined;
|
||||
/**
|
||||
* `true` if the event is trigged as a result of a switch
|
||||
* between tab navigation stacks.
|
||||
*/
|
||||
tabSwitch: boolean;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user