Closed ernsheong closed 1 year ago
Awesome suggestion! This isn't currently on our roadmap, but we're definitely interested and have some ideas floating around about how to make this work. If we make any progress, we'll let you know here.
If other folks are interested in web component support, let us know by commenting or +1-ing and we can see about prioritizing the issue.
I did some exploration of this. The querySelector
issues you brought up are one element of this, but not the main blocker for making this work in the shadow dom.
Hosted Fields (what Drop-in uses internally to make the card form) works by grabbing the sibling iframes off of the parent and then initializing them with a shared card form object. This allows the iframes to maintain a model for the validity of the card form.
When enclosed inside the shadow dom, Hosted Fields cannot access the sibling iframes, so it is unable to initialize them with a shared card form.
To support web components and the shadow dom without any weird hacks, we'd have to fundamentally change how Hosted Fields is implemented. Perhaps with a separate iframe that acts as the orchestrator that maintains the model of the card form and receives post messages from the individual fields to maintain the state of the model.
This is something we're interested in doing, but it will probably need to wait until the next major version update of braintree-web.
The PayPal portion of Drop-in uses checkout.js. Polymer support is being tracked here: https://github.com/paypal/paypal-checkout/issues/353
Using a bit of a hack, it is possible to use Drop-in with the shadow dom. Here's a simple example. The trick is to set it up outside of the shadow dom and then insert it into it: https://codepen.io/braintree/pen/VrYXYW
This user posted a code snippet for how to use Hosted Fields in a Polymer app using the slot
element: https://github.com/braintree/braintree-web/issues/226#issuecomment-298020600 A similar method should be possible with Drop-in.
Thanks for the leads. I guess the non-hacky option that could work is to put the drop-in in a global top-level (non-shadow DOM) modal. This forces the user to enter credit card in a modal, which isn't ideal but it should work.
Happy to report that slotting from the top as demonstrated in https://github.com/braintree/braintree-web/issues/226#issuecomment-298020600 works very well for me. It's an acceptable workaround. To note that the syntax for Polymer 2 is:
<my-app>
<div slot="braintree"></div>
</my-app>
Within <my-app>
:
<my-container>
<my-payment>
<slot name="braintree"></slot>
</my-payment>
</my-container>
Within <my-payment>
:
<div>Checkout</div>
<slot></slot> <-- drop in UI will appear here!
Great, I'm going to close out this issue since there's nothing else actionable for us at the moment. Glad it's working for you.
Would love it if this could be re-opened as this is not a solution but a workaround. Happy to help if you have any questions about Web Components.
@bzitzow If you can provide a solution for the problem noted here: https://github.com/braintree/braintree-web-drop-in/issues/296#issuecomment-340479173, I'd be happy to look into this again
any update on this issue? still no shadow dom support?
This is something we're actively looking into again now that the PayPal SDK we use to offer PayPal has been updated to support it.
Happy to report that slotting from the top as demonstrated in braintree/braintree-web#226 (comment) works very well for me. It's an acceptable workaround. To note that the syntax for Polymer 2 is:
<my-app> <div slot="braintree"></div> </my-app>
Within
<my-app>
:<my-container> <my-payment> <slot name="braintree"></slot> </my-payment> </my-container>
Within
<my-payment>
:<div>Checkout</div> <slot></slot> <-- drop in UI will appear here!
Hi There.
Additionally, it might help someone to mention that the usages of nested slots are the only way to fix this when the Element that needs to render the DropIn is also nested in other shadowo doms.
**Index.html**
**1st layer**
<app>
<div id="loader" class="pageloader is-active"><span class="title">Loading.</span></div>
<div slot="braintree-fields">
<!-- include nothing inside the drop-in div. do otherwise and payment braintree dropin fails.-->
<div id="drop-in"></div>
</div>
</ps-app>
**2nd layer**
<secodlayer>
<slot name="braintree-fields" slot="braintree-fields"></slot>
</secodlayer>
**3rd layer**
<thirdlayer>
<slot name="braintree-fields" slot="braintree-fields"></slot>
</thirdlayer>
etc. I lost about 6 hours messing around in order to get this right using nested slots.
I have issue here, so I vote for Support web components (lit-element) .
closing for inactivity. If you continue to encounter errors, please contact Support
General information
Issue description
https://github.com/braintree/braintree-web-drop-in/blob/master/src/dropin.js#L219 assumes that the container can be found in the global document scope.
For web components with shadow DOM encapsulation (https://developers.google.com/web/fundamentals/web-components/shadowdom), this does not work.
Some quick top of the head possible solutions:
shadowRoot
of elements recursively (naive)create
function, replacingdocument
Possible workarounds:
document.querySelector
, which is unlikely for Polymer framework)Use hosted fields integration(Update: looks likebraintree-web
also usesdocument.querySelector
, no go)There would also be styling issues because global CSS styling will not work. Everything needs to reside within the payment component shadow DOM. Once passed the shadowRoot element the dropin should be able to inject CSS, in theory.
In fact, it would make much more sense for the dropin itself to be a web-component, in the future. This provides lighter encapsulation vs. iframe.