Skip to content

Commit 82625d3

Browse files
committed
fix(router): fix navigation when clearing history and navigating before the navigatedTo event fires
1 parent 5099170 commit 82625d3

File tree

1 file changed

+45
-12
lines changed

1 file changed

+45
-12
lines changed

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

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,17 @@ function isComponentFactoryResolver(item: any): item is ComponentFactoryResolver
2929
return !!item.resolveComponentFactory;
3030
}
3131

32+
function callableOnce<T>(fn: (...args: T[]) => void) {
33+
let called = false;
34+
return (...args: T[]) => {
35+
if (called) {
36+
return;
37+
}
38+
called = true;
39+
return fn(...args);
40+
};
41+
}
42+
3243
export class DestructibleInjector implements Injector {
3344
private refs = new Set<any>();
3445
constructor(private destructibleProviders: ProviderSet, private parent: Injector) {}
@@ -71,6 +82,10 @@ export class PageRouterOutlet implements OnDestroy, RouterOutletContract {
7182
private isEmptyOutlet: boolean;
7283
private viewUtil: ViewUtil;
7384
private frame: Frame;
85+
// this function is used to clear the outlet cache (clear history)
86+
// usually it's cleared in `navigatedTo`, but on quick navigation, the event will be fired after angular already added more things to the cache
87+
// so now we call this if the component is detached or deactivated (meaning it's mid-navigation, before cache manipulation)
88+
private postNavFunction: () => void;
7489

7590
attachEvents: EventEmitter<unknown> = new EventEmitter();
7691
detachEvents: EventEmitter<unknown> = new EventEmitter();
@@ -209,6 +224,7 @@ export class PageRouterOutlet implements OnDestroy, RouterOutletContract {
209224
if (!this.isActivated) {
210225
return;
211226
}
227+
this.postNavFunction?.();
212228

213229
const c = this.activated.instance;
214230
destroyComponentRef(this.activated);
@@ -234,6 +250,8 @@ export class PageRouterOutlet implements OnDestroy, RouterOutletContract {
234250
NativeScriptDebug.routerLog(`PageRouterOutlet.detach() - ${routeToString(this._activatedRoute)}`);
235251
}
236252

253+
this.postNavFunction?.();
254+
237255
// Detach from ChangeDetection
238256
this.activated.hostView.detach();
239257

@@ -413,28 +431,43 @@ export class PageRouterOutlet implements OnDestroy, RouterOutletContract {
413431
this.locationStrategy._beginPageNavigation(this.frame, navOptions);
414432
const isReplace = navOptions.replaceUrl && !navOptions.clearHistory;
415433

434+
const currentRoute = this.activatedRoute;
416435
// Clear refCache if navigation with clearHistory
417436
if (navOptions.clearHistory) {
437+
const wipeCache = callableOnce(() => {
438+
if (this.postNavFunction === wipeCache) {
439+
this.postNavFunction = null;
440+
}
441+
if (this.outlet && this.activatedRoute === currentRoute) {
442+
// potential alternative fix (only fix children of the current outlet)
443+
// const nests = outletKey.split('/');
444+
// this.outlet.outletKeys.filter((k) => k.split('/').length >= nests.length).forEach((key) => this.routeReuseStrategy.clearCache(key));
445+
this.outlet.outletKeys.forEach((key) => this.routeReuseStrategy.clearCache(key));
446+
}
447+
});
448+
this.postNavFunction = wipeCache;
418449
const clearCallback = () =>
419450
setTimeout(() => {
420-
if (this.outlet) {
421-
// potential alternative fix (only fix children of the current outlet)
422-
// const nests = outletKey.split('/');
423-
// this.outlet.outletKeys.filter((k) => k.split('/').length >= nests.length).forEach((key) => this.routeReuseStrategy.clearCache(key));
424-
this.outlet.outletKeys.forEach((key) => this.routeReuseStrategy.clearCache(key));
425-
}
451+
wipeCache();
426452
});
427453

428454
page.once(Page.navigatedToEvent, clearCallback);
429455
} else if (navOptions.replaceUrl) {
456+
const popCache = callableOnce(() => {
457+
if (this.postNavFunction === popCache) {
458+
this.postNavFunction = null;
459+
}
460+
if (this.outlet && this.activatedRoute === currentRoute) {
461+
// potential alternative fix (only fix children of the current outlet)
462+
// const nests = outletKey.split('/');
463+
// this.outlet.outletKeys.filter((k) => k.split('/').length >= nests.length).forEach((key) => this.routeReuseStrategy.popCache(key));
464+
this.outlet.outletKeys.forEach((key) => this.routeReuseStrategy.popCache(key));
465+
}
466+
});
467+
this.postNavFunction = popCache;
430468
const clearCallback = () =>
431469
setTimeout(() => {
432-
if (this.outlet) {
433-
// potential alternative fix (only fix children of the current outlet)
434-
// const nests = outletKey.split('/');
435-
// this.outlet.outletKeys.filter((k) => k.split('/').length >= nests.length).forEach((key) => this.routeReuseStrategy.popCache(key));
436-
this.outlet.outletKeys.forEach((key) => this.routeReuseStrategy.popCache(key));
437-
}
470+
popCache();
438471
});
439472

440473
page.once(Page.navigatedToEvent, clearCallback);

0 commit comments

Comments
 (0)