How to correctly trim user input in React Native? - android

I have TextInput that receives onChangeText as a prop:
<TextInput
...
value={this.state.myString}
onChangeText={this.updateInput.bind(this)}
/>
And updateInput is represented as:
updateInput(newString) {
this.setState({ myString: newString.trim() });
}
This works for Android only. Is there some way to trim user input on both platforms (iOS, Android)?
Update
Actually, string is processed as trimmed, but you can still type as many whitespaces as you want on iOS. And if you type two whitespaces in a row the dot appears like it would be the end of the sentence. This is undesirable behaviour, is there a way to avoid it?
Link with example video: https://streamable.com/dzl3c

One way to trim like this with onChangeText property with value.trim(). Here is a working example on my RN 0.62.*
<TextInput
name="email"
type="text"
keyboardType="email-address"
keyboardAppearance="light"
returnKeyType="next"
onChangeText={value => { setValue('email', value.trim(), true) }}
blurOnSubmit={false}
onSubmitEditing={() => this.password.focus()}
autoCapitalize="none"
autoCorrect={true}
textContentType="emailAddress"
editable={!isLoading}
placeholder={Strings.INPUT_EMAIL_ADDRESS}
placeholderTextColor={Theme.GRAY_LIGHT_COLOR}
color={Theme.GRAY_DARK_COLOR}
style={[styles.input, { borderColor: errors.email ? Theme.ORANGE_COLOR : Theme.PRIMARY_DARK_COLOR }]}
ref={ref => this.email = ref} />

When you are submitting form add trim() to that value.

Related

Flatlist React native card's onPress does not trigger on Android

I am using Expo for my app. I have a horizontal Flatlist where I render my data react native paper's Card. I saw Card have onPress function. I used that to navigate the another page. But onPress function does not trigger on Android device. I know React native's touchable-opacity have positioning issue on Android. I tried hitSlop and inline styling zIndex but still does not work. I also wrap my card with react-native's touchable-opacity and play with positioning still did not help me, only it works when i used react-native-gesture-handler's touchable-opacity but then it does not work on IOS. Hope anyone can help me...
import React from 'react';
import { Card } from 'react-native-paper';
import { useNavigation } from '#react-navigation/native';
interface Iprops {
item: string;
}
export default function RenderCard({ item }: Iprops) {
const navigation = useNavigation();
return (
<Card
hitSlop={{ "bottom": 30, "top": 30, "right": 30, "left": 30 }}
onPress={() => {
navigation.navigate(`detail`, { // THIS DOES NOT TRIGGER ON ANDROID
"id": `${item.pk}`
});
}}
style={{ "marginBottom": 20 }}>
<Card.Cover
source={{ "uri": `${item.img_url}` }} />
<Card.Actions>
<Card.Title title={item.name} subtitle="Card Subtitle" />
</Card.Actions>
</Card>
);
}
I've noticed that using onPressIn or onPressOut does work on Android within an absolute positioned flatlist, but onPress does not work. I hope this might be of help to someone out there looking for an answer.
You'll need to use the TouchableOpacity element from react-native-gesture-handler.
Like you told, you should add touchable opacity to the element you are rendering on the card. TouchableOpacity can be tricky. So, first give it a styling of borderWidth:1 and borderColor to see the actual touchable area on the screen. Then you start to bring them together with the icon or the image or whatever you are rendering. TouchableOpacity works but the positioning can be tricky. You have to understand it to use it better. Think touchableOpacity as a view with borders then it'll be easier to grasp. Also, if you dont give touchableOpacity an absolute position in the styling it will be out of the screen somewhere, I was never be able to bring it to somewhere that I can see to position it. So you can add 'position' as well.
I gave up on positioning and render my component's based on Platform.
Platform.OS === `ios` ?
<Card
onPress={() => {
navigation.navigate(`detail`, {
"id": `${item.pk}`
});
}}
style={{ "marginBottom": 20 }}>
<Card.Cover source={{ "uri": `${item.img_url}` }} />
<Card.Actions>
<Card.Title title={item.name} subtitle="Card Subtitle" right={Beer} />
</Card.Actions>
</Card> :
<TouchableOpacity
onPress={() => {
navigation.navigate(`detail`, {
"id": `${item.pk}`
});
}}
>
<Card style={{ "marginBottom": 20 }}>
<Card.Cover source={{ "uri": `${item.img_url}` }} />
<Card.Actions>
<Card.Title title={item.name} subtitle="Card Subtitle" right={Beer} />
</Card.Actions>
</Card>
</TouchableOpacity>;

How to prevent copy to clipboard in TextInput react-native on Android?

I want to prevent user to copy content in TextInput but it works only on iOS but not for Android. How can I do this on Android?
[Update]: As the link #patel-dhara has given below, I already read commit about contextMenuHidden property and found that only handle onLongClick event on Android. So, still can copy to clipboard on TextInput by double-tap to it.
Here is my code:
<TextInput
style={styles.input}
placeholder="Password"
placeholderTextColor="rgba(255, 255, 255, 0.7)"
underlineColorAndroid="transparent"
secureTextEntry={isHidePass}
returnKeyType="go"
autoCapitalize="none"
onChangeText={this.handleTextChange}
onSubmitEditing={this.handleLogin}
ref={this.passwordRef}
contextMenuHidden
onBlur={() => Clipboard.setString('')}
onFocus={() => Clipboard.setString('')}
onSelectionChange={() => Clipboard.setString('')}
/>
you can use contextMenuHidden property of TextInput. It will work on both Platform Android and iOS.
<TextInput contextMenuHidden={true} />
but, It may be supported after react-native version 0.55. for more info link.
commit link for that: link
Try this:
<TextInput caretHidden={true} selectTextOnFocus={false} />
use this:
<View pointerEvents="none">
<TextInput ... />
</View>
Checkout pointer events for view:
https://facebook.github.io/react-native/docs/view#pointerevents
Another Option:
Try clearing the clipboard
<TextInput onFocus={() => Clipboard.setString('')} onSelectionChange={() => Clipboard.setString('')}/>
I you want to avoid pasting below solution works for me. I am clearing keyboard on onTouchEnd event
const [text1, setText1] = useState('')
const clearClipboard = () =>{
Clipboard.setString('')
}
const onChangeText = (text) =>{
//For android 12+ clipboard autofill option, dont allow text change more than one char..which means user is typing.
if(text1.length+1 >= text.length){
setText1(text)
}
}
<TextInput onChangeText={onChangeText} value={text1} contextMenuHidden={true} onTouchEnd={clearClipboard}></TextInput>

I want to clear the text input by providing a clear button. While iOS has support for this, I did not find any solution for android

I am totally new to React Native. I have a textinput area, I want users to clear the text they have entered completely by clicking on a button. React native provides clearButtonMode, but that is only for iOS. Looking for a solution on android devices. Here is my textinput..
<View style={editProfileStyle.textinputView}>
<TextInput
underlineColorAndroid={"rgba(0,0,0,0)"}
style={editProfileStyle.textInput}
placeholder="Enter your Name"
value={this.state.name}
onChangeText={name => this.setState({ name: name })}
/>
</View>
You have two option :
You can simply change the state.name to empty string (ie : this.setState({name : ''})
Based on RN docs , You can use clear() , You have first need to get reference to your TextInput <TextInput ref={input => { this.textInput = input }} />
and then when you need to clear you text use : this.textInput.clear()

React Native keyboard (multiline)

My question is for the keyboard type that appears when doing a multiline textinput.
<TextInput
keyboardType="default"
multiline={false}
editable={true}
onChangeText={(text) => this.updateSharedObject({note: text})}
value={this.state.data.note}
placeholder="Press to type..."
placeholderTextColor="#c0c0c0"
underlineColorAndroid="transparent"
autoCapitalize="sentences"
style={[styles.textArea, {height: this.state.height}]}
onContentSizeChange={(e) =>
this.updateSize(e.nativeEvent.contentSize.height)}
/>
When a user tries to type in the field they get this kind of keyboard.
The problem is I need to make the field a multiline field. When I set it to true the keyboard becomes this.
Is there anyway to keep the first keyboard layout while still making it multiline? I have been looking everywhere but have not found anything to help.
<TextInput returnKeyType='done' />

undefined exception while calling focus method on TextInput ref

I am trying to implement the solution proposed here for setting the focus on the next TextInput. The solution is proposed for iOS but I think it should also work for Android.
However I am getting the following exception:
undefined is not a function (evaluating '_this3.refs.Second.focus()')
I am using this Floating Label as my Text Input component. Here is my code:
<FloatingLabel
label='First'
ref='First'
validationRegex={/[A-Za-z0-9 ]+/}
value={this.props.First}
style={commonStyles.formInput}
onSubmitEditing={(event) => {this.refs.Second.focus()}}
onChangeText={(text) => this.onUpdate('First', text)}>
First</FloatingLabel>
<FloatingLabel
label='Second'
ref='Second'
style={commonStyles.formInput}
value={this.props.Second}
validationRegex={/(^([a-zA-Z]{5})([0-9]{4})([a-zA-Z]{1})$)/}
onChangeText={(text) => this.onUpdate('Second', text)}>
Second</FloatingLabel>
Can somebody help me in solving the exception? (RN 0.29, Android)
onSubmitEditing={(event) => {console.log(this.refs.Second)}} //works fine
Why am I unable to call the focus method?
this.refs.Second is a FloatingLabel object which don't have a method named "focus".
You can add a focus function to FloatingLabel component like below:
focus() {
this.refs.textInput.focus();
},
and add a ref to the TextInput in render
<View style={elementStyles}>
{this._renderLabel()}
<TextInput
ref={'textInput'}
{...props}
>
</TextInput>
</View>

Categories

Resources