Skip to content

Commit 2e475f9

Browse files
authored
fix: read navigation extras from the router navigation instead of using stored values (#88)
* fix: read navigation extras from the router navigation instead of using stored values * feat: remove navigation extras logic from location strategy * chore: fix linting issues * fix: move inject to constructor
1 parent ae23c56 commit 2e475f9

File tree

5 files changed

+41
-55
lines changed

5 files changed

+41
-55
lines changed

apps/nativescript-demo-ng/src/test.ts

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
1+
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
2+
/// <reference path="../../../node_modules/webpack/module.d.ts" />
13
import { runTestApp } from '@nativescript/unit-test-runner';
24
// import other polyfills here
35

4-
declare let require: any;
6+
// polyfills required for latest karma
7+
global.addEventListener ??= () => {
8+
// do nothing as there`s no global event listener
9+
};
10+
global.queueMicrotask ??= (fn: () => unknown) => Promise.resolve().then(fn);
511

612
runTestApp({
713
runTests: () => {

apps/nativescript-demo-ng/src/tests/ns-location-strategy.spec.ts

+5-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// make sure you import mocha-config before @angular/core
22
import { DefaultUrlSerializer, UrlTree } from '@angular/router';
3-
import { FrameService, LocationState, NSLocationStrategy, Outlet } from '@nativescript/angular';
3+
import { FrameService, LocationState, NavigationOptions, NSLocationStrategy, Outlet } from '@nativescript/angular';
44
import { BackstackEntry, Frame, NavigationEntry, Page, View } from '@nativescript/core';
55

66
export class FakeFrameService extends FrameService {
@@ -134,13 +134,13 @@ function createState(url: string, outletName: string, isPageNav: boolean = false
134134
};
135135
}
136136

137-
function simulatePageNavigation(strategy: NSLocationStrategy, url: string, frame: any, outletName?: string) {
137+
function simulatePageNavigation(strategy: NSLocationStrategy, url: string, frame: any, outletName?: string, options?: NavigationOptions) {
138138
outletName = outletName || 'primary';
139139
strategy.pushState(null, null, url, null);
140140

141141
const outlet: Outlet = strategy.findOutlet(outletName);
142142
outlet.frames.push(frame);
143-
strategy._beginPageNavigation(frame);
143+
strategy._beginPageNavigation(frame, options);
144144
}
145145

146146
function simulatePageBack(strategy: NSLocationStrategy, frame: any) {
@@ -479,8 +479,7 @@ describe('NSLocationStrategy', () => {
479479
const frame = new FakeFrame();
480480
const outletName = 'primary';
481481
// Act
482-
strategy._setNavigationOptions({ clearHistory: true });
483-
simulatePageNavigation(strategy, '/cleared', frame, outletName);
482+
simulatePageNavigation(strategy, '/cleared', frame, outletName, { clearHistory: true });
484483
const outlet: Outlet = strategy.findOutlet(outletName);
485484
// Assert
486485
assertStatesEqual(outlet.states, [createState('/cleared', outletName, true)]);
@@ -494,8 +493,7 @@ describe('NSLocationStrategy', () => {
494493
const outletName2 = 'test2';
495494

496495
// Act
497-
strategy._setNavigationOptions({ clearHistory: true });
498-
simulatePageNavigation(strategy, '/(test1:cleared//test2:test2)', frame, outletName);
496+
simulatePageNavigation(strategy, '/(test1:cleared//test2:test2)', frame, outletName, { clearHistory: true });
499497
simulatePageNavigation(strategy, '/(test1:cleared//test2:test2)', frame2, outletName2);
500498
const expectedStatesTest1: Array<LocationState> = [createState('/(test1:cleared//test2:test2)', outletName, true)];
501499
const expectedStatesTest2: Array<LocationState> = [createState('/(test1:cleared//test2:test2)', outletName2, true)];

packages/angular/src/lib/legacy/router/ns-location-strategy.ts

+16-32
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
import { Inject, Injectable, Optional } from '@angular/core';
21
import { LocationChangeEvent, LocationStrategy } from '@angular/common';
3-
import { DefaultUrlSerializer, UrlSegmentGroup, UrlTree, ActivatedRouteSnapshot, Params } from '@angular/router';
2+
import { Inject, Injectable, Optional } from '@angular/core';
3+
import { ActivatedRouteSnapshot, DefaultUrlSerializer, Params, UrlSegmentGroup, UrlTree } from '@angular/router';
44
import { Frame } from '@nativescript/core';
5+
import { START_PATH } from '../../tokens';
56
import { NativeScriptDebug } from '../../trace';
6-
import { isPresent } from '../../utils/lang-facade';
77
import { FrameService } from '../frame.service';
8-
import { Outlet, NavigationOptions, LocationState, defaultNavOptions } from './ns-location-utils';
9-
import { START_PATH } from '../../tokens';
8+
import { defaultNavOptions, LocationState, NavigationOptions, Outlet } from './ns-location-utils';
109

1110
@Injectable({
1211
providedIn: 'root',
@@ -16,7 +15,6 @@ export class NSLocationStrategy extends LocationStrategy {
1615
private currentOutlet: Outlet;
1716

1817
private popStateCallbacks = new Array<(_: any) => any>();
19-
private _currentNavigationOptions: NavigationOptions;
2018
private currentUrlTree: UrlTree;
2119

2220
public _modalNavigationDepth = 0;
@@ -42,8 +40,8 @@ export class NSLocationStrategy extends LocationStrategy {
4240
return '/';
4341
}
4442

45-
let tree = this.currentUrlTree;
46-
let changedOutlet = this.getSegmentGroupByOutlet(this.currentOutlet);
43+
const tree = this.currentUrlTree;
44+
const changedOutlet = this.getSegmentGroupByOutlet(this.currentOutlet);
4745

4846
// Handle case where the user declares a component at path "/".
4947
// The url serializer doesn't parse this url as having a primary outlet.
@@ -110,7 +108,7 @@ export class NSLocationStrategy extends LocationStrategy {
110108
currentSegmentGroup.root = urlTreeRoot;
111109

112110
const outletPath = this.getSegmentGroupFullPath(currentTree);
113-
let outletKey = this.getOutletKey(outletPath, outletName);
111+
const outletKey = this.getOutletKey(outletPath, outletName);
114112
let outlet = this.findOutlet(outletKey);
115113

116114
const parentOutletName = currentTree.outlet || '';
@@ -188,7 +186,7 @@ export class NSLocationStrategy extends LocationStrategy {
188186
}
189187
this.callPopState(state, true);
190188
} else {
191-
let state = this.currentOutlet.peekState();
189+
const state = this.currentOutlet.peekState();
192190
if (state && state.isPageNavigation) {
193191
// This was a page navigation - so navigate through frame.
194192
if (NativeScriptDebug.isLogEnabled()) {
@@ -237,7 +235,7 @@ export class NSLocationStrategy extends LocationStrategy {
237235
private callPopState(state: LocationState, pop: boolean = true, outlet?: Outlet) {
238236
outlet = outlet || this.currentOutlet;
239237
const urlSerializer = new DefaultUrlSerializer();
240-
let changedOutlet = this.getSegmentGroupByOutlet(outlet);
238+
const changedOutlet = this.getSegmentGroupByOutlet(outlet);
241239

242240
if (state && changedOutlet) {
243241
this.updateSegmentGroup(this.currentUrlTree.root, changedOutlet, state.segmentGroup);
@@ -249,7 +247,7 @@ export class NSLocationStrategy extends LocationStrategy {
249247

250248
const url = urlSerializer.serialize(this.currentUrlTree);
251249
const change: LocationChangeEvent = { state, type: 'popstate' };
252-
for (let fn of this.popStateCallbacks) {
250+
for (const fn of this.popStateCallbacks) {
253251
fn(change);
254252
}
255253
}
@@ -359,7 +357,7 @@ export class NSLocationStrategy extends LocationStrategy {
359357
}
360358
}
361359

362-
public _beginPageNavigation(frame: Frame): NavigationOptions {
360+
public _beginPageNavigation(frame: Frame, options?: NavigationOptions): NavigationOptions {
363361
if (NativeScriptDebug.isLogEnabled()) {
364362
NativeScriptDebug.routerLog('NSLocationStrategy._beginPageNavigation()');
365363
}
@@ -371,31 +369,17 @@ export class NSLocationStrategy extends LocationStrategy {
371369
lastState.isPageNavigation = true;
372370
}
373371

374-
const navOptions = this._currentNavigationOptions || defaultNavOptions;
372+
const navOptions = options || defaultNavOptions;
373+
375374
if (navOptions.clearHistory) {
376375
if (NativeScriptDebug.isLogEnabled()) {
377376
NativeScriptDebug.routerLog('NSLocationStrategy._beginPageNavigation clearing states history');
378377
}
379378
this.currentOutlet.states = [lastState];
380379
}
381-
382-
this._currentNavigationOptions = undefined;
383380
return navOptions;
384381
}
385382

386-
public _setNavigationOptions(options: NavigationOptions) {
387-
this._currentNavigationOptions = {
388-
clearHistory: isPresent(options.clearHistory) ? options.clearHistory : false,
389-
animated: isPresent(options.animated) ? options.animated : true,
390-
transition: options.transition,
391-
replaceUrl: options.replaceUrl,
392-
};
393-
394-
if (NativeScriptDebug.isLogEnabled()) {
395-
NativeScriptDebug.routerLog('NSLocationStrategy._setNavigationOptions(' + `${JSON.stringify(this._currentNavigationOptions)})`);
396-
}
397-
}
398-
399383
public _getOutlets(): Array<Outlet> {
400384
return this.outlets;
401385
}
@@ -501,7 +485,7 @@ export class NSLocationStrategy extends LocationStrategy {
501485

502486
findOutlet(outletKey: string, activatedRouteSnapshot?: ActivatedRouteSnapshot): Outlet {
503487
let outlet: Outlet = this.outlets.find((currentOutlet) => {
504-
let equalModalDepth = currentOutlet.modalNavigationDepth === this._modalNavigationDepth;
488+
const equalModalDepth = currentOutlet.modalNavigationDepth === this._modalNavigationDepth;
505489
return equalModalDepth && currentOutlet.outletKeys.indexOf(outletKey) > -1;
506490
});
507491

@@ -510,7 +494,7 @@ export class NSLocationStrategy extends LocationStrategy {
510494
if (!outlet && activatedRouteSnapshot) {
511495
const pathByOutlets = this.getPathByOutlets(activatedRouteSnapshot);
512496
outlet = this.outlets.find((currentOutlet) => {
513-
let equalModalDepth = currentOutlet.modalNavigationDepth === this._modalNavigationDepth;
497+
const equalModalDepth = currentOutlet.modalNavigationDepth === this._modalNavigationDepth;
514498
return equalModalDepth && currentOutlet.pathByOutlets === pathByOutlets;
515499
});
516500
}
@@ -520,7 +504,7 @@ export class NSLocationStrategy extends LocationStrategy {
520504

521505
private findOutletByModal(modalNavigation: number, isShowingModal?: boolean): Outlet {
522506
return this.outlets.find((outlet) => {
523-
let equalModalDepth = outlet.modalNavigationDepth === modalNavigation;
507+
const equalModalDepth = outlet.modalNavigationDepth === modalNavigation;
524508
return isShowingModal ? equalModalDepth && outlet.showingModal : equalModalDepth;
525509
});
526510
}

packages/angular/src/lib/legacy/router/page-router-outlet.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { Attribute, ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ComponentRef, Directive, Inject, InjectionToken, Injector, OnDestroy, EventEmitter, Output, Type, ViewContainerRef, ElementRef, InjectFlags, NgZone, EnvironmentInjector } from '@angular/core';
2-
import { ActivatedRoute, ActivatedRouteSnapshot, ChildrenOutletContexts, Data, PRIMARY_OUTLET, RouterOutletContract } from '@angular/router';
1+
import { Attribute, ChangeDetectorRef, ComponentFactory, ComponentFactoryResolver, ComponentRef, Directive, Inject, InjectionToken, Injector, OnDestroy, EventEmitter, Output, Type, ViewContainerRef, ElementRef, InjectFlags, NgZone, EnvironmentInjector, inject } from '@angular/core';
2+
import { ActivatedRoute, ActivatedRouteSnapshot, ChildrenOutletContexts, Data, PRIMARY_OUTLET, Router, RouterOutletContract } from '@angular/router';
33

44
import { Frame, Page, NavigatedData, profile, NavigationEntry } from '@nativescript/core';
55

@@ -10,11 +10,12 @@ import { NativeScriptDebug } from '../../trace';
1010
import { DetachedLoader } from '../../cdk/detached-loader';
1111
import { ViewUtil } from '../../view-util';
1212
import { NSLocationStrategy } from './ns-location-strategy';
13-
import { Outlet } from './ns-location-utils';
13+
import { defaultNavOptions, Outlet } from './ns-location-utils';
1414
import { NSRouteReuseStrategy } from './ns-route-reuse-strategy';
1515
import { findTopActivatedRouteNodeForOutlet, pageRouterActivatedSymbol, loaderRefSymbol, destroyComponentRef } from './page-router-outlet-utils';
1616
import { registerElement } from '../../element-registry';
1717
import { PageService } from '../../cdk/frame-page/page.service';
18+
import { ExtendedNavigationExtras } from './router-extensions';
1819

1920
export class PageRoute {
2021
activatedRoute: BehaviorSubject<ActivatedRoute>;
@@ -128,6 +129,7 @@ export class PageRouterOutlet implements OnDestroy, RouterOutletContract {
128129
@Inject(PAGE_FACTORY) private pageFactory: PageFactory,
129130
private routeReuseStrategy: NSRouteReuseStrategy,
130131
private ngZone: NgZone,
132+
private router: Router,
131133
elRef: ElementRef,
132134
viewUtil: ViewUtil
133135
) {
@@ -404,7 +406,8 @@ export class PageRouterOutlet implements OnDestroy, RouterOutletContract {
404406
}
405407
});
406408

407-
const navOptions = this.locationStrategy._beginPageNavigation(this.frame);
409+
const navOptions = { ...defaultNavOptions, ...(this.router.getCurrentNavigation().extras || {}) } as ExtendedNavigationExtras;
410+
this.locationStrategy._beginPageNavigation(this.frame, navOptions);
408411
const isReplace = navOptions.replaceUrl && !navOptions.clearHistory;
409412

410413
// Clear refCache if navigation with clearHistory

packages/angular/src/lib/legacy/router/router-extensions.ts

+6-11
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { Injectable } from '@angular/core';
2-
import { Router, UrlTree, NavigationExtras, ActivatedRoute } from '@angular/router';
2+
import { ActivatedRoute, NavigationBehaviorOptions, NavigationExtras, Router, UrlTree } from '@angular/router';
3+
import { NativeScriptDebug } from '../../trace';
4+
import { FrameService } from '../frame.service';
35
import { NSLocationStrategy } from './ns-location-strategy';
46
import { NavigationOptions, Outlet } from './ns-location-utils';
5-
import { FrameService } from '../frame.service';
6-
import { NativeScriptDebug } from '../../trace';
77
import { findTopActivatedRouteNodeForOutlet } from './page-router-outlet-utils';
88

99
export type ExtendedNavigationExtras = NavigationExtras & NavigationOptions;
10+
export type ExtendedNavigationBehaviorOptions = NavigationBehaviorOptions & NavigationOptions;
1011

1112
export interface BackNavigationOptions {
1213
outlets?: Array<string>;
@@ -20,17 +21,11 @@ export class RouterExtensions {
2021
constructor(public router: Router, public locationStrategy: NSLocationStrategy, public frameService: FrameService) {}
2122

2223
public navigate(commands: any[], extras?: ExtendedNavigationExtras): Promise<boolean> {
23-
if (extras) {
24-
this.locationStrategy._setNavigationOptions(extras);
25-
}
2624
return this.router.navigate(commands, extras);
2725
}
2826

29-
public navigateByUrl(url: string | UrlTree, options?: NavigationOptions): Promise<boolean> {
30-
if (options) {
31-
this.locationStrategy._setNavigationOptions(options);
32-
}
33-
return this.router.navigateByUrl(url);
27+
public navigateByUrl(url: string | UrlTree, options?: ExtendedNavigationBehaviorOptions): Promise<boolean> {
28+
return this.router.navigateByUrl(url, options);
3429
}
3530

3631
public back(backNavigationOptions?: BackNavigationOptions) {

0 commit comments

Comments
 (0)