refactor(core): add ApplicationRef.prototype.bootstrapImpl with an injector parameter (#60622)

This allows any components individually bootstrapped to inherit from a unique `Injector`. This is useful when bootstrapping multiple root components with different providers.

For now, the function is private while we explore potential designs to consolidate it with the existing `ApplicationRef.prototype.bootstrap` method.

PR Close #60622
This commit is contained in:
Doug Parker 2025-03-28 18:05:51 -07:00 committed by Jessica Janiuk
parent 5eccf3a5e5
commit 7cb8639da9
2 changed files with 37 additions and 1 deletions

View file

@ -498,6 +498,14 @@ export class ApplicationRef {
bootstrap<C>(
componentOrFactory: ComponentFactory<C> | Type<C>,
rootSelectorOrNode?: string | any,
): ComponentRef<C> {
return this.bootstrapImpl(componentOrFactory, rootSelectorOrNode);
}
private bootstrapImpl<C>(
componentOrFactory: ComponentFactory<C> | Type<C>,
rootSelectorOrNode?: string | any,
injector: Injector = Injector.NULL,
): ComponentRef<C> {
profiler(ProfilerEvent.BootstrapComponentStart);
@ -532,7 +540,7 @@ export class ApplicationRef {
? undefined
: this._injector.get(NgModuleRef);
const selectorOrNode = rootSelectorOrNode || componentFactory.selector;
const compRef = componentFactory.create(Injector.NULL, [], selectorOrNode, ngModule);
const compRef = componentFactory.create(injector, [], selectorOrNode, ngModule);
const nativeElement = compRef.location.nativeElement;
const testability = compRef.injector.get(TESTABILITY, null);
testability?.registerApplication(nativeElement);

View file

@ -256,6 +256,34 @@ describe('bootstrap', () => {
),
);
});
describe('bootstrapImpl', () => {
it('should use a provided injector', inject([ApplicationRef], (ref: ApplicationRef) => {
class MyService {}
const myService = new MyService();
@Component({
selector: 'injecting-component',
template: `<div>Hello, World!</div>`,
})
class InjectingComponent {
constructor(readonly myService: MyService) {}
}
const injector = Injector.create({
providers: [{provide: MyService, useValue: myService}],
});
createRootEl('injecting-component');
const appRef = ref as unknown as {bootstrapImpl: ApplicationRef['bootstrapImpl']};
const compRef = appRef.bootstrapImpl(
InjectingComponent,
/* rootSelectorOrNode */ undefined,
injector,
);
expect(compRef.instance.myService).toBe(myService);
}));
});
});
describe('destroy', () => {