angular: Structural Directive's provides are no longer available in template as of Angular 4.0

I’m submitting a … (check one with “x”)

[X] bug report => search github for a similar issue or PR before submitting
[ ] feature request
[ ] support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior I may be a unicorn wanting this behavior, but when a template is constructed from a structural directive with providers the providers are not made available to components within the template.

Expected behavior In version 2.x the providers were available to components within the template and should still be available in 4.x.

Minimal reproduction of the problem with instructions

Angular 4.0 https://plnkr.co/edit/xgJmWalVRShMWveolG9I?p=preview throws error ERROR Error: No provider for ThingToBeProvided!

Angular 2.4.1 https://plnkr.co/edit/qDFsvElHhvQe0mEhDuRQ?p=preview works as expected

What is the motivation / use case for changing the behavior?

Please tell us about your environment:

  • Angular version: 2.0.X 4.0.2 (You should update this boilerplate ^ to reflect the new versioning)

  • Browser: [all | Chrome XX | Firefox XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ]

  • Language: [all | TypeScript X.X | ES6/7 | ES5]

  • Node (for AoT issues): node --version =

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 8
  • Comments: 22 (9 by maintainers)

Most upvoted comments

I’m trying to understand if this issue applies to my problem. I have a standard directive used to inject a “theme” into child components:

<ng-container [myButtonTheme]="'titlebar'">
  <!-- this button receives 'titlebar' as an Optional constructor parameter -->
  <my-button icon="far fa-times"></sv-button>
</ng-container>

I also have a structural directive used to identify page title templates:

<ng-container *myPageTitle>
  <!-- I would like to have this button receive a 'titlebar' injected token. -->
  <my-button icon="far fa-times"></sv-button>
</ng-container>

AFAICT, currently there is no way to pass “something” from the structural directive myPageTitle to the components instantiated into the template. Which doesn’t make ANY sense, to me: myPageTitle IS a parent of my-button and the template scoping should be like the JavaScript lexical scoping.

Any considerations upon my case or insights on why on earth the structural directive is not a parent of the button, would be really appreciated.

The problem seems to be actually in TemplateRef.createEmbeddedView (used by ViewContainerRef.createEmbeddedView), see https://github.com/angular/angular/blob/c8a1a14b87e5907458e8e87021e47f9796cb3257/packages/core/src/view/refs.ts#L318 TemplateRef is created using parentView of the template, and that cannot be changed. Along with it, it inherits Injector and few other properties.

The behavior is clearly shown here: https://stackblitz.com/edit/angular-3bcv2q The template is reused in two places, however since it is bound to the context of the template, not the context where it is actually included, it might create quite confusing behavior (but someone might rely on this).

@thekalinga i think you did not provide sufficient DOM. I assume complete output is:

<!--template bindings={}-->
<h1>
  From parent<br>
  <!--template bindings={}--><span>From child</span>
 </h1>

where first is <!--template bindings={}--> is *appInlineEdit, and second <!--template bindings={}--> is *appShowOnEdit

But this just for better understanding that

I’m not sure if the above observation is true.

It is true. You see that directives are not in child-parent communication. But only produced DOM is.

Anyway, look at the comment above your - they plan to support this Dependency Injection in future.