Repository navigation
Description
Centralizing discussion on Shadow DOM V1 changeover.
Good explainer documentation on what's changed between v0 -> v1: https://hayato.io/2016/shadowdomv1/
Shadow Root Changes:
element.createShadowRoot() => .attachShadow({ mode: 'open' | 'closed' })
This is the big change, currently breaking people using Edge (unexpectedly), as it supports the new Shadow DOM API but not the old.
Proposed Fix:
- Add two new
ViewEncapsulationenum options:ShadowDomandClosedShadowDom(name to be bikeshedded) - doing this rather than changing the behavior ofViewEncapsulation.Nativemeans we can do this as a feature release rather than a breaking change.ViewEncapsulation.Nativeshould be deprecated.
Shadow DOM emulation / ViewEncapsulation.Emulated:
Currently the Emulated view encapsulation is based on the V0 semantics.
Proposed Fix:
We should update the emulation of Shadow DOM via Shadow CSS to match the V1 semantics - we currently use an (old) version of the ShadowCSS polyfill from @webcomponents - https://github.com/angular/angular/blob/c8a1a14b87e5907458e8e87021e47f9796cb3257/packages/compiler/src/shadow_css.ts.
Additionally, we should consider allowing developers to polyfill Shadow DOM at runtime via the Shadow DOM polyfill at https://www.webcomponents.org/polyfills. This would allow developers to author with the expectation of Shadow DOM being available, and fall back via the polyfill, rather than having to author two components etc to support modern and legacy browsers. This polyfill has a non-trivial runtime overhead, but as all major browsers (except Edge ) support it, this may be desirable for some developers.
::content selector => ::slotted (compound-selector)
V1 introduces a new psuedo-selector for styling slotted nodes. This is of course supported natively, but we should work out the correct way to (maybe) emulate this in encapsulated mode, what to do about ng-deep, etc.
Content Projection Changes
<content> elements are deprecated, in favor of the new <slot> API. <slot> has already been added to the schema, so developers are able to use native slot functionality (this is generally only useful in Angular Elements, for now).
Proposed Fix:
@pkozlowski-opensource has proposed a new <ng-slot> API that would supersede <ng-content> - this means aligning with the distribution semantics of the V1 API. This may mean introducing something like @SlotChild()/@SlotChildren() decorators and deprecating @ContentChild()/@ContentChildren().
Additionally, we should align the semantics of how our emulated distribution of nodes works against the V1 spec, including default content: #12530
Longer term, we should consider if the part/theme proposal covers our developers' use cases, and potentially emulate it at build time for theming? See #22515
Activity
robwormald commentedon May 1, 2018
The Shadow DOM fix is the most time-critical, as it's confusing for developers - many browsers never supported the V0 API, but now support the V1, which Angular doesn't support.
Chrome has also deprecated v0 - https://www.chromestatus.com/feature/4507242028072960
cyrilletuzi commentedon May 2, 2018
Does this mean even Angular Elements still use the ShadowDOM v0? If so, it's a serious issue: as one the goal of Elements is to produce standard web components, it needs to have proper ShadowDOM support.
sarunint commentedon May 2, 2018
Is this issue going to be pre-v6 or post-v6 thing?
robwormald commentedon May 2, 2018
@cyrilletuzi yes, that's why I opened the issue.
@sarunint not likely to land in 6.0, but we can probably do the initial work as additive for a 6.x release
DanielNetzer commentedon May 2, 2018
is there any workaround that we can use to support angular/elements for Edge/IE11 till this fix will be released?
robwormald commentedon May 2, 2018
@DanielNetzer as of this writing, neither Edge nor IE11 support Shadow DOM, so its a non-issue there. Use
ViewEncapsulation.Emulated.sandangel commentedon May 3, 2018
@robwormald Hi, may I ask 2 questions?
1/ does this means we should not use Angular Element in production yet until Angular team release a version that compatible with Shadow DOM v1?
2/ The proposed fix with Content Projection seems like a big breaking change, is that all we have to do is replace all ng-content, ContentChild, ContentChildren with ng-slot, SlotChild, SlotChildren to update? If so hopefully
ng updatecommand could do that job.trotyl commentedon May 3, 2018
@sandangel Angular Element is just a wrapper for normal Angular Dynamic Component, without any special runtime behavior, all Angular Components are using
ViewEncapsulation.Emulatedby default, so are Angular Elements.To be more clear, Angular Elements do care about Custom Elements, but not Shadow DOM, Template Tag nor HTML Import.
sandangel commentedon May 3, 2018
@trotyl hi, thanks for your answer.
I think different: angular element use Emulated by default, but since we can put it anywhere, is that safer to use ViewEncapsulation.Native instead? In that situation does moving to Shadow V1 introduce some breaking change? (like we have to change to ViewEncapsulation.ShadowDom / ClosedShadowDom).
trotyl commentedon May 3, 2018
@sandangel I won't suggest
ViewEncapsulation.Nativefor now, given:EmulatedandNativecomponents may sometimes break encapsulation like ViewEncapsulation.Emulated/ViewEncapsulation.Native behave differently on child components #20449, also bad for performance as copying styles everywhere (to make interop work), and 3rd-party libs are not likely to useNative;I'm not sure about the migration path, but all breaking changes for valid API usage should follow the Angular Deprecation Policy, providing at least two-major-version deprecation stage.
@robwormald This should also cover #12530 which is supported by Shadow DOM V1.
1 remaining item
benoitjchevalier commentedon Jun 14, 2018
Can we hope this makes it into Angular 7? We're building a library of Web Components using Angular Elements and possibly including other Web Components built with other libraries (Polymer), which will be using Shadow Dom. Having v1 Shadow Dom support [and polyfilling Shadow Dom (v1), but that can be done on our side] will probably be a need for us as we won't be able to mix V0 component with V1 components.
Aligning content projection to use slots would also help standardizing the use of our components. I'm also hoping it will make it easier grabbing a ref to another web component that has been projected into an angular element (I'm having a hard time finding a clean way of doing it with @ContentChild right now)
akanass commentedon Jun 20, 2018
Hope we can have a solution soon because
ViewEncapsulation.Nativeis broken onSafariand mycustomElementdoesn’t work on it.Thanks for your collaboration and your time on this problem.
Thilo84 commentedon Jun 21, 2018
I'm also waiting for a working solution for the
ViewEncapsulation.Native. There is currently no working polyfill for IE.I would be very happy if this pull request https://github.com/angular/angular/pull/19059 could be merged soon.
Thank you very much for your effort.
robwormald commentedon Jun 30, 2018
Update on this - #24718 should fix the root issue (the renderer using the old Shadow DOM API) - it's an opt-in as
ViewEncapsulation.ShadowDom- note that using the new Shadow DOM API will likely impact styles if you are relying on the old API (that's why it's a new option).Note that this API (like the existing
Nativeoption) requires Shadow DOM to be available in the browser, and provides no polyfills or benefits for browsers that do not support Shadow DOM (At this writing, Chrome and Safari support v1, Firefox support is imminent and Edge's status is unknown. IE will never support Shadow DOM.schnrap commentedon Jul 15, 2018
Does this new
ViewEncapsulation.ShadowDomoffer a way to access the host children other than @ContentChildren? Or do we need to wait for a new option like a @SlotChildren for this (like suggested above)?robwormald commentedon Jul 16, 2018
@schnrap it does not add anything additional for
@ContentChildren- we'll look at something for this post-ivy. For the moment, you can use the(slotchange)event,slot.assignedNodes()andnode.assignedSlot(), as well as just vanillashadowRoot.querySelectororMutationObserverschnrap commentedon Jul 20, 2018
I got it working this way, perfect!
Thank you very much for your time and help.
robwormald commentedon Sep 25, 2018
implemented in c9844a2
benoitjchevalier commentedon Sep 25, 2018
@robwormald with this closed is there any plan to support shadow dom polyfills and in particular css variables in Angular Elements?
evanjmg commentedon Aug 12, 2019
Any update on shadow DOM polyfills?
angular-automatic-lock-bot commentedon Sep 15, 2019
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
This action has been performed automatically by a bot.