Stripe introduced a way to collect credit cards information named Stripe Elements.
Roughly speaking, it consists on letting Stripe propose an UI for collecting credit cards.
I used it in an Ionic3/Angular4 application.
For now, it works perfectly, except I found a very annoying bug, in iOS only:
When focusing the credit card number, a keyboard appears (seems to be the native one), then it is replaced by the ionic one 0,5 second after, as showed on these 2 iPhone screenshots:
- https://i.stack.imgur.com/qO5YB.png
- https://i.stack.imgur.com/p23Y7.png
That would not be a problem usually.
But then, if I press “back” button, I go to the previous page but the keyboard stays! Even if I close the keyboard, it will reopen forever as soon as I go to a new page, or if I open the menu… my UI is broken.
I have the intuition there is a conflict between the ionic keyboard triggered on any input, and the native keyboard triggered by Stripe code.
But due to the nature of stripe Elements, I can’t control the content of the form, I only have pretty much this in the html code:
<form action="/charge" method="post" id="payment-form">
<div class="form-row">
<div id="card-element">
<!-- a Stripe Element will be inserted here. -->
</div>
....
</form>
Any idea how to try to debug this?
Do you think I could tell to Ionic not to trigger the keyboard?
Thanks a lot.
Notes : I’m using ionic-angular 3.7.1
I have the same issue as well. I fixed it by inserting an invisible input node. Once purchase / next button is pressed, or anytime you decide to hide the keyboard, focus on that invisible input and then blur.
<input id="inviInput" type="tel" style="border: 0px; color: transparent; width: 0px; height: 0px; background: transparent;">
var inviInput = $('#inviInput')[0];
inviInput.focus();
inviInput.blur();
Any approach to get the DOM node shall be fine, even for pure Javascript.
Note that the input shall not be "display: none;", or "visibility: hidden;", otherwise iOS Safari won't focus on it.
EDIT with specific solution for Ionic3/Angular4:
<input #invisiInput
id="invisiInput"
type="tel"
style="border: 0; color: transparent; width: 0; height: 0; background: transparent;">
--
@ViewChild('invisiInput') invisiInput: ElementRef;
...
ionViewWillLeave() {
this.invisiInput.nativeElement.focus();
this.invisiInput.nativeElement.blur();
}
UPDATE
The following approach might be better:
$('.card_input iframe')[0].focus()
$('.card_input iframe')[0].blur()
Get the iframe and blur.
Ok sound like Stripe isn't going to fix this anytime soon and have suggested the same method of focus then blur. Here's their response for completeness.
For PCI reasons our fields are hosted in iframes and mobile safari has been fairly bad since last version with how it handles hidden iframes. There are potential fixes here we could implement but they would likely introduce more issues in the long run so we're still looking into a better solution.
Hopefully there is a workaround here and it should be fairly simple.
The problem comes from the fact Safari ignores the .blur() if the
iframe is unfocused which then causes the keyboard to stay open. What
you can do is to call the .focus() and .blur() methods manually which
would reset the state.
Update
Also I found that none of the suggestions worked and the keyboard would remain open. What you actually need to do is use Stripe's own focus and blur methods i.e;
const card = elements.create('card');
card.focus();
setTimeout(() => {
card.blur();
});
I had to add the setTimeout in my angular app as without it the blur didn't seem to work.
I have reported this issue to Stripe and they have acknowledged that there is an issue and it's being looked into, so hopefully there will be a fix soon.