-
Notifications
You must be signed in to change notification settings - Fork 4.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ViewEncapsulation.ShadowDom breaks components #9471
Comments
Same problem here. We want to use PrimeNG components inside of web components and the ViewEncapsulation.ShadowDom indeed breaks most components. I just had a deeper look into the calendar. Two functions of the calendar are problematic:
The only solution for me right now would be to fork PrimeNG and fix it or create a directive that overrides those functions of the component. |
Thank you @AKoempel. I will try to solve that with directive, as you proposed. Also with some components, I will migrate to material, they updated js recently and it works like a harm! Unless, of course, PrimeFaces will upgrade js in the library too. |
We're also using ViewEncapsulation.ShadowDom and, in our case, it was the behavior of any overlay panel. It appeared and disapeared right away when the user clicked on the component to show (e.g. a user clicks in a multiselect, options appear and disapear very quickly). As @AKoempel said, we ended up overidding "isOutsideClicked(event)" function in primeng-multiselect.js and primeng-dropdown.js |
Also, since v. 11.2.1, it's breaking with the following error: The root cause seems to be this commit: For now, we're leaving on v. 11.2.0 (on which we had to create directives to override problematic functions in the component). We're also planning to leave primeng in the near future if these issues persist, since we have to use shaddow dom and clearly primeng isn't compatible with it. |
Is this still an issue? |
@raymatos yes, it's still an issue, I'm having the issue for all components has something "dropdown": Dropdown, Calendar, tooltip,... |
Here's what I found (with solution below): the issue caused by this line: https://github.com/primefaces/primeng/blob/master/src/app/components/dom/domhandler.ts#L175 PrimeNg uses I manage to solve this issue, not much effort:
// from this
let parents = this.getParents(element);
// to this
let parents = this.getParents(element).filter(item => !(item instanceof ShadowRoot)); Explain: we filter out the shadow root when getting parents of
@Directive({
selector: '[bindScrollListener]',
})
export class bindScrollListenerDirective {
constructor(
@Host() @Self() @Optional() public hostSel: Dropdown) {
// Nothing is changed here, I just simply use ConnectedOverlayScrollHandler from the 2 files we downloaded
hostSel.bindScrollListener = () => {
if (!hostSel.scrollHandler) {
hostSel.scrollHandler = new ConnectedOverlayScrollHandler(hostSel.containerViewChild.nativeElement, (event: any) => {
if (hostSel.overlayVisible) {
hostSel.hide();
}
});
}
hostSel.scrollHandler.bindScrollListener();
}
// override PrimeNG to make it support ShadowDOM
hostSel.isOutsideClicked = (event: any) => {
const target = event.target.shadowRoot ? event.path[0] : event.target
return !(this.hostSel.el.nativeElement.isSameNode(target) || this.hostSel.el.nativeElement.contains(target) || (this.hostSel.overlay && this.hostSel.overlay.contains(<Node> target)));
}
}
} Finally register the directive in
What I actually changed:
hostSel.isOutsideClicked = (event: any) => {
const target = event.target.shadowRoot ? event.path[0] : event.target
return !(this.hostSel.el.nativeElement.isSameNode(target) || this.hostSel.el.nativeElement.contains(target) || (this.hostSel.overlay && this.hostSel.overlay.contains(<Node> target)));
} P/s: for each component that has this issue you need to create a directive for it (above I use Hi @cagataycivici, I don't know if you aware of this issue, but if this one is fixed it'll make PrimeNg much better cuz it can run in all kind of encapsulation environments that Angular has. Also Shadow DOM is a common case when developers want to embed their Angular components into any other web app. If my solution is valid, I'd happy to create a PR for that |
Hi @yigitfindikli If you ever have time please help to look at this issue. Thank you |
For anyone is having this issue, I've published a small lib with directives that fix this problem: https://github.com/maitrungduc1410/primeng-shadowdom-directives |
Hi @maitrungduc1410, thank you, I was waiting for some update here, I have a problem with filters in datatable, the <p-columnFilter "> element. In the library that you provided is there any solution for this element? |
It's PrimeNg table right? |
Yeah of course, below is my question for this issue on stackoverflow |
okay I'll update to support for that too (if it's possible :D) |
Hi @ContrRus , I just looked into the question you posted on StackOverflow, it seems not related to this Github issue, I posted my answer for your question |
Hello Team, @yigitfindikli , Would be really great if we could get the fix for this in upcoming primeng version. I think it is quite relevant now as we use micro front end architecture and we may need to integrate the angular micro front ends to existing web application as remote modules with shadow DOM encapsulation |
the issue opened at Oct 29, 2020, more than a year ago, is there any ETA ? |
Having the same problem in our team's project. Really waiting for this fix |
@maitrungduc1410, thanks for the directives. Is it possible to add one for ConfirmPopup ? |
@vanroda okay, I'll check and let you know |
Hi @vanroda, please upgrade to version |
I really wish this would be fixed in the newer version of primeng. It's been over a year. I too have my components break once I switch to ViewEncapsaulation.ShadowDom. |
@leopardy this Github issue only happens to "overlay" components, in your case there's no such component usage in DataView, I did check, and it works fine inside ShadowDOM. I think you probably import css incorrectly Remember that when working with ShadowDOM, global style defined in The way it works is you have to place css import in any component which is ShadowDOM encapsulated. Example: @Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: [
'./app.component.scss',
// ---------------- IMPORT PRIMENG STYLE HERE
"../../../../node_modules/primeicons/primeicons.css",
"../../../../node_modules/primeng/resources/themes/saga-blue/theme.css",
"../../../../node_modules/primeng/resources/primeng.min.css"
],
encapsulation: ViewEncapsulation.ShadowDom
})
export class AppComponent { |
Answer removed. |
Still have the same issue within the webcomponents? @cagataycivici |
Still not working in shadow dom. >﹏< |
Sorry right now, ShadowDOM is not supported and I'm not sure how it can be right now. Any ideas are appreciated considering the current design agnostic theming approach of PrimeNG. For web components though, we'll create PrimeElements aka PrimeUI with lit or similar which will have a styling architecture suited for WC. PrimeNG supports NONE and EMULATED for now. |
Any rough estimate when PrimeElements could be created? |
@cagataycivici What do you think of the approach by @maitrungduc1410 ?
As I understand, the root problem is with "overlay" behaviors of components. Other than that, simply using A quick guess from me (I haven't really looked well into how @maitrungduc1410 did it): solving this is probably just a matter of being careful to create all overlay elements also inside the shadow root, rather than appending Thank you all!! This package is awesome 🚀 |
For my case, the following patch seems to be enough for now: import { DomHandler } from 'primeng/dom';
// Patch it to use `.parentElement` instead of `.parentNode`.
// See https://github.com/primefaces/primeng/issues/9471
// See https://github.com/primefaces/primeng/blob/ddcc166fe48d336012f2dfa9a2deb6af08f98593/src/app/components/dom/domhandler.ts#L164-L166
DomHandler.getParents = function(element, parents = []) {
const parent = element.parentElement;
return parent ? this.getParents(parent, [...parents, parent]) : parents;
}; Many thanks to @maitrungduc1410! |
the solution proposed seems good, can you apply it? can you share the ETA? |
I'll discuss it with the team this week and respond. PrimeUI begins in december. |
Hi, So sorry for the delayed response! Improvements have been made to many components recently, both in terms of performance and enhancement. Therefore, this improvement may have been developed in another issue ticket without realizing it. You can check this in the documentation. If there is no improvement on this, can you reopen the issue so we can include it in our roadmap? Best Regards, |
In case anyone else lands here I found a solution specifically for using a ColumnFilter.prototype.onOverlayAnimationStart = patchedOnOverlayStart
...
function patchedOnOverlayStart(event){
switch (event.toState) {
case 'visible':
this.overlay = event.element;
const sdr = document.body.querySelector('my-shadow-dom-component').shadowRoot
// get an instance of your shadowRoot
sdr.appendChild(this.overlay);
ZIndexUtils.set('overlay', this.overlay, this.config.zIndex.overlay);
DomHandler.absolutePosition(this.overlay, this.icon.nativeElement);
this.bindDocumentClickListener();
this.bindDocumentResizeListener();
this.bindScrollListener();
this.overlayEventListener = (e) => {
if (this.overlay && this.overlay.contains(e.target)) {
this.selfClick = true;
}
};
this.overlaySubscription = this.overlayService.clickObservable.subscribe(this.overlayEventListener);
break;
case 'void':
this.onOverlayHide();
if (this.overlaySubscription) {
this.overlaySubscription.unsubscribe();
}
break;
}
} Basically I override the The code otherwise the same as https://github.com/primefaces/primeng/blob/master/src/app/components/table/table.ts#L4611 Also keep in mind that when you are using this inside a module federated frontend or something similar to revert the override once finished, might break stuff for others otherwise. |
The issue persists on version 17.0.0. In my case, it opens the calendar, but It cannot be interacted. |
I'm submitting a ... (check one with "x")
Plunkr Case (Bug Reports)
https://stackblitz.com/edit/primeng-autocomplete-demo-aha9nr
Current behavior
Enabling ViewEncapsulation.ShadowDom in Angular's component, embedded prime's component doesn't work.
Expected behavior
ViewEncapsulation.ShadowDom in Angular's component should not break embedded prime component.
Minimal reproduction of the problem with instructions
Use ViewEncapsulation.ShadowDom in components with embedded prime's component.
What is the motivation / use case for changing the behavior?
Possibility to use the library in microfrontends, where using ShadowDom is crucial.
Angular version 10.X
PrimeNg version 10.X
The text was updated successfully, but these errors were encountered: