Ionic应用中Stripe Elements银行卡输入框焦点与键盘异常问题
Hey there, let's fix those two Stripe Elements headaches in your Ionic 3 app right away! I've dealt with similar issues before, so here's what you need to do:
Problem 1: iOS keyboard closes & jumps to date field after card number is entered
This usually happens due to Stripe's default behavior for the combined card element, paired with iOS webview's form input handling. The fix is to use individual Stripe Elements (card number, expiry, CVC) instead of the single card element—this gives you full control over focus and keyboard behavior.
Problem 2: Can't keep focus on the card number input
Looking at your code, I spotted the immediate issue: you're calling this.card.blur() inside a setTimeout right after this.card.focus()! That's actively making the input lose focus. We'll remove that, plus adjust the timing of when you mount and focus the element.
Step-by-Step Solution
1. Update your component code
First, install the Ionic Keyboard plugin to help control iOS keyboard behavior (if you haven't already):
ionic cordova plugin add ionic-plugin-keyboard npm install @ionic-native/keyboard
Then modify your component logic to use individual elements and fix focus handling:
import { Component, ViewChild, ElementRef } from '@angular/core'; import { Keyboard } from '@ionic-native/keyboard'; import { NavController } from 'ionic-angular'; declare var stripe: any; // Assuming Stripe is loaded globally @Component({ selector: 'page-payment', templateUrl: 'payment.html' }) export class PaymentPage { @ViewChild('cardContainer') cardContainer: ElementRef; private cardNumber: any; private cardExpiry: any; private cardCvc: any; constructor(private keyboard: Keyboard, private navCtrl: NavController) {} ionViewDidEnter() { // Wait until the view is fully loaded before initializing Stripe Elements const stripeStyle = { base: { fontSize: '16px', color: '#333', '::placeholder': { color: '#aaa' } }, invalid: { color: '#e53935' } }; const elements = stripe.elements(); // Create individual elements instead of the combined "card" element this.cardNumber = elements.create('cardNumber', { style: stripeStyle }); this.cardExpiry = elements.create('cardExpiry', { style: stripeStyle }); this.cardCvc = elements.create('cardCvc', { style: stripeStyle }); // Mount each element to its DOM container this.cardNumber.mount(this.cardContainer.nativeElement.querySelector('#card-number')); this.cardExpiry.mount(this.cardContainer.nativeElement.querySelector('#card-expiry')); this.cardCvc.mount(this.cardContainer.nativeElement.querySelector('#card-cvc')); // Fix Problem 1: Control focus when card number is fully entered this.cardNumber.addEventListener('change', (event) => { if (event.complete) { // Manually focus the expiry field this.cardExpiry.focus(); // Force keyboard to stay open on iOS (webview quirk) this.keyboard.show(); } }); // Fix Problem 2: Ensure card number input gets and keeps focus setTimeout(() => { this.cardNumber.focus(); this.keyboard.show(); }, 300); // Small delay to ensure elements are fully mounted // Attach your existing handler to all elements this.cardNumber.addEventListener('change', this.cardHandler.bind(this)); this.cardExpiry.addEventListener('change', this.cardHandler.bind(this)); this.cardCvc.addEventListener('change', this.cardHandler.bind(this)); } cardHandler(event) { // Your existing logic for handling input changes/errors console.log('Card element changed:', event); if (event.error) { // Show error message to user } } }
2. Update your template
Replace your single card container with separate containers for each element:
<ion-content padding> <h3>Enter Payment Details</h3> <div #cardContainer> <div id="card-number" class="stripe-input"></div> <div id="card-expiry" class="stripe-input"></div> <div id="card-cvc" class="stripe-input"></div> </div> <button ion-button block (click)="processPayment()">Submit Payment</button> </ion-content>
3. Add basic styling (optional but helpful)
Add some CSS to space out the inputs:
.stripe-input { margin: 15px 0; padding: 10px; border: 1px solid #ddd; border-radius: 4px; }
Key Fixes Explained
- Removed the
blur()call: That line was the main reason your card number input couldn't keep focus. - Used individual elements: This avoids Stripe's automatic focus jumping that was causing the iOS keyboard to close.
- Timed focus with
ionViewDidEnter: We initialize elements after the view is fully loaded, so the DOM containers exist when we mount them. - Keyboard plugin integration: Forces the iOS keyboard to stay open when switching between inputs, which fixes the unexpected close issue.
内容的提问来源于stack exchange,提问作者EfosaSO

