Repository navigation
injector yields wrong result inside embedded view #54097
Description
Which @angular/* package(s) are the source of the bug?
core, forms
Is this a regression?
No
Description
Inside an embedded view with an associated injector the injector seems to return an unexpected result, even if the host flag is used.
We've got a nested form, and formControlName uses @Host() when injecting its container
| @Optional() @Host() @SkipSelf() parent: ControlContainer, |
Our inner form is contained in an ng-template. In the repro below we just instantiate it next to the ng-template itself, in our real code the template outlet would be somewhere else entirely in the application (and DOM).
<!-- outer component -->
<form [formGroup]="outerForm">
<wrapper-component />
</form>
<!-- wrapper component -->
<ng-container [ngTemplateOutlet]="tpl" [ngTemplateOutletInjector]="injector" />
<ng-template #tpl>
<inner-component />
</ng-template>
<!-- inner component -->
<form [formGroup]="innerForm">
<input formControlName="innerInput">
</form>While registering the formControlName="innerInput" an error is thrown. Debugging the issue shows that the formControlName actually gets the outer form as its form.
Please provide a link to a minimal reproduction of the bug
https://stackblitz.com/edit/stackblitz-starters-vvqjnr?file=src%2Fmain.ts
Please provide the exception or error you saw
Error: Cannot find control with name: 'innerInput'
at _throwError (forms.mjs:3208:11)
at setUpControl (forms.mjs:2991:13)
at FormGroupDirective.addControl (forms.mjs:4902:9)
at FormControlName._setUpControl (forms.mjs:5499:43)
at FormControlName.ngOnChanges (forms.mjs:5444:18)
at FormControlName.rememberChangeHistoryAndInvokeOnChangesHook (core.mjs:2561:14)
at callHookInternal (core.mjs:3603:14)
at callHook (core.mjs:3634:9)
at callHooks (core.mjs:3585:17)
at executeInitAndCheckHooks (core.mjs:3535:9)
Please provide the environment you discovered this bug in (run ng version)
I've verified the described behaviour is present in Angular 16.1.9, 16.2.12, and 17.1.1.
Anything else?
Removing the ngTemplateOutletInjector solves the issue, which makes me question whether it's necessary to pass along an injector. The documentation on the injector input/parameter (both for the ngTemplateOutlet directive and for createEmbeddedView on ViewContainerRef or TemplateRef) doesn't really yield any useful information.
Activity
ChristofferGersen commentedon Sep 30, 2024
I also ran into this today, with Angular version 18.2.1. I believe the problem here is that once you specify
ngTemplateOutletInjector, then that injector is always consulted first inside the referenced template. You would expect element injectors to be consulted first, up to the top of the referenced template, and only then consult the providedngTemplateOutletInjector.This breaks the reactive form directives, because they try to resolve a
ControlContainer. So if the providedngTemplateOutletInjectorprovides that, then all reactive form directives inside the referenced template will use that value, regardless of any directives that provide a new value.Markiewic commentedon Apr 3, 2025
Ran into this after upgrading from Angular 15 to 16. Looks like it's a regression after all.
waterplea commentedon Oct 15, 2026
I believe it is the same bug as this one:
#57390
@JeanMeche can we get this on the team radar? It's really annoying and very unexpected.
JeanMeche commentedon Oct 17, 2026
In #57390 you mention that the issue might have been fixed in v20, and indeed I don't seem to be able to reproduce it anymore.
But I see that the issue you have for taiga-family/taiga-ui#15227 runs v21. Could you please provide a narrowed repro of the issue ?
waterplea commentedon Oct 17, 2026
No, Taiga UI is currently on v19, so if it's fixed in v20 that's good. That particular issue ended up being something else. Glad to hear it's fixed, I suppose this one and the one I linked can be resolved now if you cannot reproduce them anymore.
injectorfor templates breaks@Hostinject flag #57390 as a duplicate of this issueJeanMeche commentedon Oct 17, 2026
As #71408 shows, there is still an issue that we need to resolve.