Skip to content

Commit f1d9d22

Browse files
committed
feat(router-outlet): add swipeGesture prop to control swipe-to-go-back per outlet
1 parent 1886864 commit f1d9d22

19 files changed

Lines changed: 567 additions & 283 deletions

File tree

BREAKING.md

Lines changed: 22 additions & 263 deletions
Large diffs are not rendered by default.

BREAKING_ARCHIVE/v8.md

Lines changed: 282 additions & 0 deletions
Large diffs are not rendered by default.

core/api.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,6 +1589,7 @@ ion-router-outlet,shadow
15891589
ion-router-outlet,prop,animated,boolean,true,false,false
15901590
ion-router-outlet,prop,animation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
15911591
ion-router-outlet,prop,mode,"ios" | "md",getIonMode(this),false,false
1592+
ion-router-outlet,prop,swipeGesture,boolean | undefined,undefined,false,false
15921593

15931594
ion-row,shadow
15941595

core/src/components.d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2915,6 +2915,10 @@ export namespace Components {
29152915
*/
29162916
"mode": "ios" | "md";
29172917
"setRouteId": (id: string, params: ComponentProps | undefined, direction: RouterDirection, animation?: AnimationBuilder) => Promise<RouteWrite>;
2918+
/**
2919+
* If `true`, the router-outlet should allow navigation via swipe-to-go-back gesture. Defaults to `true` for `"ios"` mode and `false` for `"md"` mode.
2920+
*/
2921+
"swipeGesture"?: boolean;
29182922
"swipeHandler"?: SwipeGestureHandler;
29192923
}
29202924
interface IonRow {
@@ -8229,6 +8233,10 @@ declare namespace LocalJSX {
82298233
"onIonNavDidChange"?: (event: IonRouterOutletCustomEvent<void>) => void;
82308234
"onIonNavWillChange"?: (event: IonRouterOutletCustomEvent<void>) => void;
82318235
"onIonNavWillLoad"?: (event: IonRouterOutletCustomEvent<void>) => void;
8236+
/**
8237+
* If `true`, the router-outlet should allow navigation via swipe-to-go-back gesture. Defaults to `true` for `"ios"` mode and `false` for `"md"` mode.
8238+
*/
8239+
"swipeGesture"?: boolean;
82328240
"swipeHandler"?: SwipeGestureHandler;
82338241
}
82348242
interface IonRow {
@@ -9723,6 +9731,7 @@ declare namespace LocalJSX {
97239731
interface IonRouterOutletAttributes {
97249732
"mode": "ios" | "md";
97259733
"animated": boolean;
9734+
"swipeGesture": boolean;
97269735
}
97279736
interface IonSearchbarAttributes {
97289737
"color": Color;

core/src/components/router-outlet/router-outlet.tsx

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,21 @@ export class RouterOutlet implements ComponentInterface, NavOutlet {
5353
/** This property allows to create custom transition using AnimationBuilder functions. */
5454
@Prop() animation?: AnimationBuilder;
5555

56+
/**
57+
* If `true`, the router-outlet should allow navigation via swipe-to-go-back gesture.
58+
* Defaults to `true` for `"ios"` mode and `false` for `"md"` mode.
59+
*/
60+
@Prop({ mutable: true }) swipeGesture?: boolean;
61+
@Watch('swipeGesture')
62+
swipeGestureChanged() {
63+
this.updateGestureEnabled();
64+
}
65+
5666
/** @internal */
5767
@Prop() swipeHandler?: SwipeGestureHandler;
5868
@Watch('swipeHandler')
5969
swipeHandlerChanged() {
60-
if (this.gesture) {
61-
this.gesture.enable(this.swipeHandler !== undefined);
62-
}
70+
this.updateGestureEnabled();
6371
}
6472

6573
/** @internal */
@@ -121,13 +129,24 @@ export class RouterOutlet implements ComponentInterface, NavOutlet {
121129
}
122130
}
123131
);
124-
this.swipeHandlerChanged();
132+
133+
if (this.swipeGesture === undefined) {
134+
this.swipeGesture = config.getBoolean('swipeBackEnabled', this.mode === 'ios');
135+
} else {
136+
this.updateGestureEnabled();
137+
}
125138
}
126139

127140
componentWillLoad() {
128141
this.ionNavWillLoad.emit();
129142
}
130143

144+
private updateGestureEnabled() {
145+
if (this.gesture) {
146+
this.gesture.enable(this.swipeHandler !== undefined && this.swipeGesture === true);
147+
}
148+
}
149+
131150
disconnectedCallback() {
132151
if (this.gesture) {
133152
this.gesture.destroy();

packages/angular/common/src/directives/navigation/router-outlet.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ export abstract class IonRouterOutlet implements OnDestroy, OnInit {
108108
onEnd: (shouldContinue) => this.stackCtrl.endBackTransition(shouldContinue),
109109
}
110110
: undefined;
111+
112+
this.nativeEl.swipeGesture = swipe;
111113
}
112114

113115
constructor(

packages/angular/test/base/e2e/src/lazy/routing.spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,22 @@ test.describe('Routing', () => {
1919
await expect(page.locator('app-router-link-page')).toHaveAttribute('class', 'ion-page can-go-back');
2020
});
2121

22+
test('should not swipe back when swipeGesture is false', async ({ page }) => {
23+
await page.locator('#routerLink').click();
24+
25+
await ionPageHidden(page, 'app-router-link');
26+
await ionPageVisible(page, 'app-router-link-page');
27+
28+
await page.locator('ion-router-outlet').evaluate((el: any) => {
29+
el.swipeGesture = false;
30+
});
31+
32+
await ionSwipeToGoBack(page, true);
33+
34+
await ionPageVisible(page, 'app-router-link-page');
35+
await ionPageHidden(page, 'app-router-link');
36+
});
37+
2238
test('should swipe and go back', async ({ page }) => {
2339
await page.locator('#routerLink').click();
2440

packages/react-router/src/ReactRouter/StackManager.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { RouteInfo, StackContextState, ViewItem } from '@ionic/react';
2-
import { RouteManagerContext, StackContext, generateId, getConfig } from '@ionic/react';
2+
import { RouteManagerContext, StackContext, generateId } from '@ionic/react';
33
import React from 'react';
44

55
import { clonePageElement } from './clonePageElement';
@@ -211,12 +211,6 @@ export class StackManager extends React.PureComponent<StackManagerProps, StackMa
211211

212212
async setupRouterOutlet(routerOutlet: HTMLIonRouterOutletElement) {
213213
const canStart = () => {
214-
const config = getConfig();
215-
const swipeEnabled = config && config.get('swipeBackEnabled', routerOutlet.mode === 'ios');
216-
if (!swipeEnabled) {
217-
return false;
218-
}
219-
220214
const { routeInfo } = this.props;
221215

222216
const propsToUse =

packages/react-router/test/base/src/App.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import NestedOutlet2 from './pages/nested-outlet/NestedOutlet2';
3131
import ReplaceAction from './pages/replace-action/Replace';
3232
import TabsContext from './pages/tab-context/TabContext';
3333
import { OutletRef } from './pages/outlet-ref/OutletRef';
34-
import { SwipeToGoBack } from './pages/swipe-to-go-back/SwipToGoBack';
34+
import { SwipeToGoBack, SwipeToGoBackDisabled } from './pages/swipe-to-go-back/SwipToGoBack';
3535
import Refs from './pages/refs/Refs';
3636
import DynamicIonpageClassnames from './pages/dynamic-ionpage-classnames/DynamicIonpageClassnames';
3737
import Tabs from './pages/tabs/Tabs';
@@ -57,6 +57,7 @@ const App: React.FC = () => {
5757
<Route path="/tab-context" component={TabsContext} />
5858
<Route path="/outlet-ref" component={OutletRef} />
5959
<Route path="/swipe-to-go-back" component={SwipeToGoBack} />
60+
<Route path="/swipe-to-go-back-disabled" component={SwipeToGoBackDisabled} />
6061
<Route path="/dynamic-ionpage-classnames" component={DynamicIonpageClassnames} />
6162
<Route path="/tabs" component={Tabs} />
6263
<Route path="/tabs-secondary" component={TabsSecondary} />

packages/react-router/test/base/src/pages/Main.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ const Main: React.FC<MainProps> = () => {
5252
<IonItem routerLink="/swipe-to-go-back">
5353
<IonLabel>Swipe to go back</IonLabel>
5454
</IonItem>
55+
<IonItem routerLink="/swipe-to-go-back-disabled">
56+
<IonLabel>Swipe to go back (disabled)</IonLabel>
57+
</IonItem>
5558
<IonItem routerLink="/dynamic-ionpage-classnames">
5659
<IonLabel>Dynamic IonPage Classnames</IonLabel>
5760
</IonItem>

0 commit comments

Comments
 (0)