Projected content is not hidden when dynamically creating a component if there is nowhere to project the content yet #54881
Labels
area: core
Issues related to the framework runtime
core: content projection
core: dynamic view creation
Milestone
Which @angular/* package(s) are the source of the bug?
core
Is this a regression?
No
Description
When creating a component dynamically via
ViewContainerRef.createComponent()
, any content children created viaViewContainerRef.createEmbeddedView()
and provided throughoptions.projectableContent
are not detached from the document if the dynamically created component does not have a location to project content to yet. Instead, they remain attached to the document outside of the component they were supposed to be projected into. If this is not the intended way to do this, please correct me, but this was the only way I found to data bind the embedded view to the component its template was declared in.This situation arises with components that don't project content, or conditionally project content. For components with conditionally projected content specifically, once there is a location to project the content, the content will be moved there. If that location becomes unavailable again later, the projected content is properly detached from the document.
I expect projecting content in dynamically created components to be consistent with projecting content declaratively, which will always detach the content to project from the document if there is nowhere to project it. If this inconsistency is intentional, then I expect there to be a documented solution for replicating the behavior of projecting content declaratively when dynamically creating a component.
Please provide a link to a minimal reproduction of the bug
https://stackblitz.com/edit/projected-content-not-hidden-dynamic-components?file=src%2Fapp%2Fapp.component.html
Please provide the exception or error you saw
N/A. No errors in console.
Please provide the environment you discovered this bug in (run
ng version
)Anything else?
There is a single workaround for both the no projectable content and conditionally projectable content cases, which is to use
Renderer2
to manually detach the elements created in the embedded view from the document before providing them to the component. I have provided examples of this workaround in the linked StackBlitz.I am aware that this issue could theoretically be solved by using the suggested alternative to
<ng-content>
for conditional content projection, but my attempted solution of passingTemplateRef.element.nativeElement
(which is just a comment) inoptions.projectableNodes
when creating the component that projects content would not let me retrieve theTemplateRef
via@ContentChild
later.I discovered this issue while implementing the longstanding workaround for cdkDragHandle being ignored when it is placed inside a child component for my dynamically created components. I figure it is worth mentioning as that issue was closed without an official solution over 5 years ago on the basis that it was not possible at the time. It might be worth revisiting if it is possible now.
The text was updated successfully, but these errors were encountered: