Skip to content

Commit

Permalink
refactor(router): use real EnvironmentInjector in the `RouterOutlet…
Browse files Browse the repository at this point in the history
…` class

Currently, the `RouterOutlet` class uses a custom injector implementation to provide route-specific tokens (such as `ActivatedRoute`). This commit switches Router logic to use real `EnvironmentInjector` instead.

This commit partially addresses issue angular#54864 and there will be one more PR with extra changes to defer logic.
  • Loading branch information
AndrewKushnir committed Mar 18, 2024
1 parent 2ed0992 commit 8dc9b18
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 26 deletions.
1 change: 1 addition & 0 deletions packages/core/src/core_render3_private_export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -323,5 +323,6 @@ export {depsTracker as ɵdepsTracker, USE_RUNTIME_DEPS_TRACKER_FOR_JIT as ɵUSE_
export {generateStandaloneInDeclarationsError as ɵgenerateStandaloneInDeclarationsError} from './render3/jit/module';
export {getAsyncClassMetadataFn as ɵgetAsyncClassMetadataFn} from './render3/metadata';
export {InputFlags as ɵɵInputFlags} from './render3/interfaces/input_flags';
export {createEnvironmentInjectorWithScope as ɵcreateEnvironmentInjectorWithScope} from './render3/ng_module_ref';

// clang-format on
43 changes: 17 additions & 26 deletions packages/router/src/directives/router_outlet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ import {
inject,
Injectable,
InjectionToken,
Injector,
Input,
OnDestroy,
OnInit,
Output,
reflectComponentType,
SimpleChanges,
ViewContainerRef,
ɵcreateEnvironmentInjectorWithScope as createEnvironmentInjectorWithScope,
ɵRuntimeError as RuntimeError,
} from '@angular/core';
import {combineLatest, of, Subscription} from 'rxjs';
Expand Down Expand Up @@ -359,13 +359,23 @@ export class RouterOutlet implements OnDestroy, OnInit, RouterOutletContract {
const snapshot = activatedRoute.snapshot;
const component = snapshot.component!;
const childContexts = this.parentContexts.getOrCreateContext(this.name).children;
const injector = new OutletInjector(activatedRoute, childContexts, location.injector);
const providers = [
{provide: ActivatedRoute, useValue: activatedRoute},
{provide: ChildrenOutletContexts, useValue: childContexts},
];

// TODO: add a comment on why we do not have `any` scope here.
const scopes = new Set<any>(['environment']);
this.activated = location.createComponent(component, {
index: location.length,
injector,
environmentInjector: environmentInjector,
injector: location.injector,
environmentInjector: createEnvironmentInjectorWithScope(
providers,
environmentInjector,
scopes,
),
});

// Calling `markForCheck` to make sure we will run the change detection when the
// `RouterOutlet` is inside a `ChangeDetectionStrategy.OnPush` component.
this.changeDetector.markForCheck();
Expand All @@ -374,26 +384,6 @@ export class RouterOutlet implements OnDestroy, OnInit, RouterOutletContract {
}
}

class OutletInjector implements Injector {
constructor(
private route: ActivatedRoute,
private childContexts: ChildrenOutletContexts,
private parent: Injector,
) {}

get(token: any, notFoundValue?: any): any {
if (token === ActivatedRoute) {
return this.route;
}

if (token === ChildrenOutletContexts) {
return this.childContexts;
}

return this.parent.get(token, notFoundValue);
}
}

export const INPUT_BINDER = new InjectionToken<RoutedComponentInputBinder>('');

/**
Expand Down Expand Up @@ -434,8 +424,9 @@ export class RoutedComponentInputBinder {
.pipe(
switchMap(([queryParams, params, data], index) => {
data = {...queryParams, ...params, ...data};
// Get the first result from the data subscription synchronously so it's available to
// the component as soon as possible (and doesn't require a second change detection).
// Get the first result from the data subscription synchronously so it's available
// to the component as soon as possible (and doesn't require a second change
// detection).
if (index === 0) {
return of(data);
}
Expand Down

0 comments on commit 8dc9b18

Please sign in to comment.