3

I've been experimenting with the dynamic component loader in Angular2. An issue, possibly related to this: https://github.com/angular/angular/issues/4330 , seems to be that once a component is loaded with, say, the loadIntoLocation() function, the injector cannot find the parent component's injector or the things that were injected into it. As that article suggests, you can pass an array of Resolved Providers obtained from the parent's injector (Injector.resolve) into the last parameter of loadIntoLocation().

This seems to work initially, but I have also found that any children of the dynamically loaded components also have the same problem. The injector of the children does not know to look up the injection tree for providers, so a standard injection in the constructor of the children like

   constructor( myComponent: MyComponent)

does not work. The children (of the dynamically loaded components) are not dynamically loaded but just "normally" instantiated using a template, selector etc. I am wondering:

  1. Is this (still) a known issue or am I misunderstanding anything?
  2. If a known issue is there any workaround at the child level? I tried a constructor as above and also using @Host and also using forward ref + @host but none work. Is there another way to manually pass bindings to a component that is not dynamically loaded?
  3. Is there any other possible workaround for this?

2 Answers 2

0

The problems seems to be caused by the resolved providers passed to loadToLocation(). DI is hierarchical and DI tries to resolve required types by walking the hierarchy towards the root, but the chain is broken at loadToLocation() because there providers are passed instead of a child-injector.
The dynamically added component and its children can only resolve providers passed to loadToLocation() or listed in the providers list of the dynamically added component itself (or one of its children if it is a (grand-)parent of the actually resolved component).

When DI walks upwards from within the dynamically inserted tree to resolve a dependency, the iteration stops at the component added by loadToLocation() because the injector of this component doesn't have a parent injector (which would be the injector of the host component where the dynamically added component was added).

See also https://github.com/angular/angular/issues/5990

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for that link - it seems to have some more ideas to try. Just to be clear, in my experience, the dynamic load not only causes the Injector tree to be broken, but ALL subsequent child components of dynamically loaded components cannot walk up their trees either (which is a little different than what you said). Every child seemingly gets placed in its own injector tree. Thus the listed work arounds need to repeated somehow for every single child which is untenable. Happy to be proven wrong on that... I'll take a look at your link and see if I can get it to work. Thanks much.
I have not investigated in full detail. If it is as you say then I think this is a bug and should be reported. That the tree is broken for the dynamically added element is obvious though and I guess this will be fixed.
0

Correction on this. I have conflated another problem in my code with what I thought was the bug described above. The children of my dynamically loaded component were derived from abstract classes. I was trying to inject the abstract class into the children as opposed to the actual implementation which, per this

Interface based programming with TypeScript, Angular 2 & SystemJS

I have learned you cannot do. The injection tree does get broken upon a dynamic load (which I do think should be corrected), but I take back the part about the children thereafter not being able to traverse their own tree. Thanks for the comments - it helped me sort it out.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.