- Notifications
You must be signed in to change notification settings - Fork26.7k
Description
Which @angular/* package(s) are the source of the bug?
elements
Is this a regression?
No
Description
Angular Elements currently supports "content projection" from the initial render during component upgrade when children are already present.
My main issue with it is that neither the DOM nor custom elements have any meaningful semantics for what "content projection" means in a way compatible with Angular. You can always create a DOM element and then add children to it, but if that element is creating children of its own, there is no distinction between its children and your "content projected" children. This conceptual flaw manifests in a few ways.
First, Angular only performs content projection on component upgrade (typically when attached to the document). If you later add children to the element, this does not get projected into an<ng-content>
slot and just gets appended to the host element.
Second, content projection maymove elements, meaning what originally looks like:
<my-comp><divid="hello">Hello, World!</div></my-comp>
Post-upgrade might suddenly look like:
<my-comp><div>Goodbye, World!</div><span><divid="hello">Hello, World!</div></span></my-comp>
The component's internal template confuses the expected contract of content projection.myComp.firstElementChild
no longer refers to#hello
, and instead refers to#goodbye
. This is relatively understandable in the context of a light DOM tree, but it means that we've lost the distinction between the projected content and the internal component content. This is necessary tochange the projected content, which is no longer easily possible. Even if you keep a reference to the projected element and replace it in the DOM, Angular retains a reference to the old element and will continue to project it.
This movement also makes it impossible to recreate the underlying Angular component because moving the projected children means we can no longer find them as direct children of the custom element, the process is not repeatable. This is problematic formanaging the component lifecycle as indicatedhere.
It is my belief that content projection as Angular understands it is fundamentally incompatible with custom elements and the way the DOM works. I think the only sane behavior here is to remove the feature altogether and require Angular Elements to be empty during the initial render, allowing Angular full control over their contents.
I think the one subcase which can be made to work is if the underlying Angular component usesViewEncapsulation.ShadowDom
. This solves most of the conceptual issues as the light/shadow distinction disambiguates between elements provided in content projection and elements owned by the component template directly. Consumers can mutate element children at any time and see those reflected in the expected way. This likely requires some non-trivial changes to Angular internals to make content projection fit the<slot>
model, but at least in theory I believe this does "square the circle" with respect to content projection in custom elements.
Please provide a link to a minimal reproduction of the bug
Please provide the exception or error you saw
Please provide the environment you discovered this bug in (runng version
)
v20
Anything else?
No response