angular / angular/angular

Angular Elements content projection should require Shadow DOM

Offen
#64,228 0 Kommentare 3 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
area: elements
Vorherrschende Sprache
TypeScript
Sterne
101k
Forks
27.5k
Ø Merge
1 T. 19 Std.
Gemergte PRs (30 T.)
288

Beschreibung

### 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 `` slot and just gets appended to the host element.

Second, content projection may _move_ elements, meaning what originally looks like:

```html

Hello, World!

```

Post-upgrade might suddenly look like:

```html

Goodbye, World!


Hello, World!

```

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 to _change_ 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 for [managing the component lifecycle](https://github.com/angular/angular/issues/64229) as indicated [here](https://github.com/angular/angular/issues/38778#issuecomment-690433315).

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 uses `ViewEncapsulation.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 `` 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

https://stackblitz.com/edit/stackblitz-starters-9edtpmzx?description=An%20angular-cli%20project%20based%20on%20@angular/animations,%20@angular/common,%20@angular/compiler,%20@angular/core,%20@angular/forms,%20@angular/platform-browser,%20@angular/platform-browser-dynamic,%20@angular/router,%20core-js,%20rxjs,%20tslib%20and%20zone.js&file=src%2Fmain.ts,src%2Findex.html&template=node&title=Angular%20Starter

### Please provide the exception or error you saw

```true

```

### Please provide the environment you discovered this bug in (run `ng version`)

```true
v20
```

### Anything else?

_No response_

Beitragsleitfaden

Beitragsleitfaden öffnen

Rechercherichtung

Beginne mit dem @angular/elements-Paket und reproduziere das Verhalten anhand des verknüpften StackBlitz-Beispiels, mit Fokus auf die anfängliche Inhaltsprojektion, das spätere Einfügen von Kindern und die Neuerstellung der Komponente. Das Issue nennt keine Quelldateien oder Tests; für den Abschluss wären ein abgestimmtes Design und eine entsprechende Regressionstestabdeckung für Shadow DOM oder das Verhalten bei einer anfänglich leeren Darstellung erforderlich.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
angular, typescript
Bereich
frontend
Issue-Typ
Bug
Schwierigkeit
5/5
Geschätzter Aufwand
Über eine Woche
Aktivitätsstatus
Veraltet
Klarheit
Muss geklärt werden
Anfängerfreundlichkeit
25/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.