Skip to content
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

Unable to dismiss the keyboard using CardField #222

Closed
travisobregon opened this issue May 14, 2021 · 14 comments · Fixed by #260
Closed

Unable to dismiss the keyboard using CardField #222

travisobregon opened this issue May 14, 2021 · 14 comments · Fixed by #260
Labels
enhancement New feature or request P1 Address these issues second

Comments

@travisobregon
Copy link

Describe the bug
There is no way to dismiss the keyboard (by pressing "Done", or taping away) using the CardField component from what I can tell. This is the same behavior in the example project as well.

To Reproduce
Steps to reproduce the behavior:

  1. Use the CardField component on a screen
  2. Tap into the field to open the keyboard

Expected behavior
A user can easily dismiss the keyboard.

@arekkubaczkowski
Copy link
Collaborator

arekkubaczkowski commented May 18, 2021

Hi, thanks for flagging.
Yeah it is because internal react-native behaviors work only with build-in TextInput component https://github.com/facebook/react-native/blob/174753600778675c8b0e7d341b6044192af68d00/Libraries/Components/ScrollView/ScrollView.js#L1380

In this case we have to handle it manually, so we need to track screen interactions and dismiss the keyboard if needed. To achieve this I propose to that stripe sdk will expose extra UI component which will take care of it. To use it you will have to wrap your entire screen where is the CardInput, with our component.
cc @thorsten-stripe

@smeetagrawal
Copy link

smeetagrawal commented May 31, 2021

Can anyone provide more information as how I can dismiss the keyboard, because I am searching for it, is there any property or method we need to call in order to dismiss keyboard when clicked outside the CardField input.

@arekkubaczkowski
Copy link
Collaborator

you have to wrap your screen with <StripeContainer /> component

@smeetagrawal
Copy link

smeetagrawal commented May 31, 2021

If I understand properly, you mean to say

  • First I have to import StripeContainer component like this import { StripeContainer, CardField } from "@stripe/stripe-react-native"
  • Then wrap screen with like below
<StripeContainer>
	<SafeAreaView>
		<ScrollView>
			<View>
				<CardField
					postalCodeEnabled={false}
					placeholder={{
						number: "4242 4242 4242 4242",
					}}
					cardStyle={{
						backgroundColor: "#FFFFFF",
						textColor: "#000000",
					}}
					style={{
						width: "100%",
						height: 50,
						marginVertical: 30,
						borderWidth: 1,
						borderColor: "#000",
					}}
					onCardChange={(cardDetails) => {
						setCard(cardDetails);
					}}
					onFocus={(focusedField) => {
						console.info("focusField", focusedField);
					}}
				/>
			</View>
		</ScrollView>
	</SafeAreaView>
</StripeContainer>

@smeetagrawal
Copy link

smeetagrawal commented May 31, 2021

But above code is not working and I am also not able to get StripeContainer from @stripe/stripe-react-native like below.
import { StripeContainer } from "@stripe/stripe-react-native"

Version "@stripe/stripe-react-native": "^0.1.2"

It will be good, If you can send any reference for dismissing keyboard when click outside of CardField, Because I am not able to get any working example yet.

@thorsten-stripe
Copy link
Contributor

@smeetagrawal StripeContainer has been added here (#260) and will be available starting v0.1.3. If you need it earlier, you can clone down the master branch and build and install the library locally: https://github.com/stripe/stripe-react-native/blob/master/CONTRIBUTING.md#install-library-as-local-repository

@aganov
Copy link
Collaborator

aganov commented Jun 3, 2021

Is there any way to call endEditing on ios manually? Our use case involves custom bottom sheet (where CardField is rendered and we want to close the keyboard when bottom sheet is dismissed.

Edit:

I was able to deal with this issue by calling self.endEditing(true) in removeFromSuperview

// CardFieldView.swift
override func removeFromSuperview() {
    self.endEditing(true)
    self.delegate?.onDidDestroyViewInstance(id: CARD_FIELD_INSTANCE_ID)
}

and then force re-render when bottom sheet is closed, this will close the kbd too...

const [key, setKey] = useState(1);
<BottomSheetModal onDismiss={() => setKey(key + 1)}>
  <CardField key={key} />
</BottomSheetModal>

I still prefer to be able to call endEditing manually, but seems like there is no other way around... In theory we just need <CardField ref={cardFieldRef} />; cardFieldRef.current.blur(); to close the keyboard... Something like this https://gist.github.com/aganov/eaffbb691848299458df449a58de3979

@cinnabarcaracal
Copy link
Collaborator

cinnabarcaracal commented Jun 8, 2021

Does anyone have any ideas on how to dismiss the keyboard without the press triggering something else?

We have the CardField in a scrollview containing other payment methods (things like loyalty points), and if you click off to dismiss the keyboard it is very easy to accidentally swap the payment method for something else.

The best I can come up with so far is to track when the field is in use and disable the all of the other elements on screen. Bit tricky without an onBlur handler though

Edit: I have shuffled things around so if someone presses another element while the CardField is in focus, that removes our tracking of the field being in focus (it also prevents the normal behaviour when pressing those elements). This let me work around a lack of onBlur, but it would be a lot cleaner if that existed.

Even cleaner would be some way (maybe prop driven) to make it so if you press outside of the keyboard (and maybe check they aren't pressing the field component?), the keyboard is dismissed without the press doing anything else. I think I could do this purely in RN by putting up some kind transparent View on top of the entire screen based on the field having focus, but I don't know how I would still let the user press into the different sub-fields of the CardField component

@thorsten-stripe
Copy link
Contributor

@cinnabarcaracal thanks for outlining your workaround. I've copied this to the onBlur issue.

@johanjq
Copy link

johanjq commented Sep 20, 2021

Hi everyone! I'm still not able to resolve this, I've a modal with a TextInput from react-native and a <CardField /> coming from @stripe/stripe-react-native v0.1.4. When you focus the <TextInput /> and then press somewhere else, the keyboard dismisses correctly. but this doesn't happen with the <CardField />. Is there any way to resolve this? I tried wrapping the view with a < StripeContainer /> but that didn't work.

Thanks so much everyone!

Screen.Recording.2021-09-20.at.10.11.38.mov

@edi
Copy link

edi commented Nov 2, 2021

@johanjq You need to add keyboardShouldPersistTaps="never" to <StripeContainer /> in order for the keyboard to get dismissed.

It defaults to always, which is wrong in my opinion.

@matthewmturner
Copy link

keyboardShouldPersistTaps="never" worked on iOS but it seems android is expecting a boolean.

@akandaurov
Copy link

am also not able to get StripeContainer from @stripe/stripe-react-native like below. import { StripeContainer } from "@stripe/stripe-react-native"

Version "@stripe/stripe-react-native": "^0.1.2"

It will be good, If you can send any reference for dismissing keyboard when click outside of CardField, Because I am not able to get any working example yet.

It's just boolean
<StripeContainer keyboardShouldPersistTaps={false}>

@johnsonfash
Copy link

For bottomsheetmodal

Use the CardForm ref to control keyboard dismiss.

`
const cardRef = useRef<CardFormView.Methods>(null)
const [cardFocus, setCardFocus] = useState(false);

<Pressable
onPress={() => {
if (cardFocus) {
cardRef.current?.blur()
setCardFocus(false);
}
}}

....other view components
<Pressable onPress={() => {
if (!cardFocus) {
cardRef.current?.focus()
setCardFocus(true)
}
}}>


`

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request P1 Address these issues second
Projects
None yet
Development

Successfully merging a pull request may close this issue.