Skip to content

Commit ab1ac53

Browse files
authored
feat: emit onRendered event when location and status are settled (#15)
1 parent 6d72754 commit ab1ac53

File tree

6 files changed

+35
-108
lines changed

6 files changed

+35
-108
lines changed

package-lock.json

Lines changed: 0 additions & 103 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

projects/router/src/lib/create-router.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,19 @@ export class NgRouter<
9696
routerState = linkedSignal(() => this.state);
9797
isTransitioning = signal(false);
9898

99+
private status = computed(() => this.routerState().status);
100+
private prevStatus = linkedSignal<'pending' | 'idle', 'pending' | 'idle'>({
101+
source: this.status,
102+
computation: (src, prev) => prev?.source ?? src,
103+
});
104+
private location = computed(() => this.routerState().location);
105+
private prevLocation = linkedSignal<
106+
ReturnType<typeof this.location>,
107+
ReturnType<typeof this.location> | undefined
108+
>({
109+
source: this.location,
110+
computation: (src, prev) => prev?.source,
111+
});
99112
private matches = computed(() => this.routerState().matches);
100113

101114
hasPendingMatches = computed(() =>
@@ -145,6 +158,20 @@ export class NgRouter<
145158
};
146159
}
147160

161+
effect(() => {
162+
const [prevLocation, location] = [this.prevLocation(), this.location()];
163+
if (prevLocation && location.state.key === prevLocation?.state.key) {
164+
return;
165+
}
166+
167+
const [prevStatus, status] = [this.prevStatus(), this.status()];
168+
169+
// when the router transitions from non-idle to idle, we emit a `onRendered` event
170+
if (prevStatus !== 'idle' && status === 'idle') {
171+
this.emit({ type: 'onRendered', ...getLocationChangeInfo(this.state) });
172+
}
173+
});
174+
148175
effect((onCleanup) => {
149176
const unsub = this.__store.subscribe(() => {
150177
this.routerState.set(this.state);

projects/router/src/lib/link.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ export class Link {
248248

249249
private preloadTimeout: ReturnType<typeof setTimeout> | null = null;
250250
protected handleMouseEnter(event: MouseEvent) {
251-
if (this.disabled() || !this.preload()) return;
251+
if (this.disabled() || !this.preload() || this.isActive()) return;
252252

253253
this.preloadTimeout = setTimeout(() => {
254254
this.preloadTimeout = null;

projects/router/src/lib/router.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,11 @@ export function provideRouter(
6363
},
6464
provideAppInitializer(() => {
6565
const router = injectRouter();
66-
router.load().then(() => {
67-
console.log('initial router load');
66+
router.load({ sync: true }).then(() => {
67+
// upon initial load, we'll set the router state to idle if it's not already
68+
if (router.state.status !== 'idle') {
69+
router.__store.setState((s) => ({ ...s, status: 'idle' }));
70+
}
6871
});
6972
return Promise.resolve();
7073
}),

src/app/about/about.route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ export const AboutRoute = createRoute({
1212
pendingComponent: () => Spinner,
1313
loader: async () => {
1414
const todosService = inject(TodosClient);
15-
await new Promise((resolve) => setTimeout(resolve, 5_000));
1615
const todos = await firstValueFrom(todosService.getTodo(1));
16+
await new Promise((resolve) => setTimeout(resolve, 5_000));
1717
return { todos };
1818
},
1919
}).lazy(() => import('./about').then((m) => m.LazyAboutRoute));

src/app/app.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
<h1>Welcome to {{ title }}!</h1>
1313
<a link="/" class="chau">Home</a>
1414
|
15-
<a link="/about">About</a>
15+
<a [link]="{ to: '/about', preload: 'intent' }">About</a>
1616
|
1717
<a [link]="{ to: '/parent' }" [linkActive]="{ exact: false }">Parent 1</a>
1818
|

0 commit comments

Comments
 (0)