How to programmatically select text in a TextInput component - react-native

Is there a way to programmatically highlight/select text that is inside a TextInput component?

You can use selectTextOnFocus to achieve this. This will ensure that all text inside the TextInput is highlighted when the field is tapped into.

Actually you can, by accessing textInput's method by refs.
<TextInput ref={input => this.myInput = input} selectTextOnFocus style={{height: 100, width: 100}} defaultValue='Hey there' />
and where you want to select all text programmatically you can
this.myInput.focus()
works on iOS, not sure about android.
Reference : http://facebook.github.io/react-native/releases/0.45/docs/textinput.html#selectionstate

I don't know if there's a better way, but I found a workaround. The text has to be focused first. Here's an example
import React { Component } from 'react';
import { Button, TextInput, findNodeHandle } from 'react-native';
import TextInputState from 'react-native/lib/TextInputState';
class MyComponent extends Component {
render() {
return (
<View style={{ flex: 1, }}>
<Button
title="select text"
onPress={() => {
TextInputState.focusTextInput(findNodeHandle(this.inputRef))
}}
</
<TextInput
selectTextOnFocus
ref={ref => this.inputRef = ref}
/>
</View>
);
}
}

I'm here to share my findings. In a List, you might encounter that selectTextOnFocus is broken. In this case you can use this method selection. From React-Native I found this:
In my case I had trouble with the selectTextOnFocus prop in a list. So I had to add a debounce function to work with selection prop.
const [shouldSelect, setShouldSelect] = useState(undefined);
const onFocus = () =>{
setShouldSelect({start:0, end:String(text).length});
}
const focus = useCallback(_.debounce(onFocus,500),[shouldSelect]);
<TextInput
selection={shouldSelect}
onBlur={()=>setShouldSelect(undefined)}
onFocus={()=>focus()}// this is important
selectTextOnFocus
ref={r=>onRef(r)}
keyboardType={'number-pad'}
autoCorrect={false}
blurOnSubmit={false}
returnKeyType={'done'}
underlineColorIos={'transparent'}
underlineColorAndroid={'white'}
allowFontScaling={false}
value={String(text)}
/>

this.inputRef.focus() sets focus to the TextInput component, and then the flag you set in the attributes selectTextOnFocus does the rest.

Note: For those who wants to use selectTextOnFocus short answer. Actually, it works fine in IOS, but doesn't work in Android.
Thanks to Arnav Yagnik; Following is a similar approach in a functional component:
const inputRef = React.useRef(null);
React.useEffect(() => {
if (inputRef.current) {
console.log('focusing !');
inputRef.current.focus();
}
}, []);
return <TextInput
multiline
label="Amount"
selectTextOnFocus
placeholder="Write Count"
value={stockCount.toString()}
/>

Related

React-Native TextInput for registering a user Why is the typed text is not displaying or being stored into the setInput object?

Hello I am trying to navigate creating a text input on React-Native that lets the user enter their email password and name and stores it in the object. But it is not working how I expected and I am not sure where I have gone wrong. I have looked at similar projects online but most are done with React not react-natie and even still when i try their implementation it still doesnt fix the text not displaying as i type or allowing it to be store when the user presses the register button.
import { Text, View, TextInput, Button, StyleSheet} from 'react-native';
import {useState} from 'react';
export default function Home() {
const [input, setInput] = useState({
fullName:"",
email:"",
password: "",
});
const inputHandler = (e) => {
let name = e.target.fullName
let value = e.target.value;
setInput({
...input,
[name]: value,
});
};
const registerUser = (e) => {
e.preventDefault();
console.log(input)
setInput({
fullName:"",
email: "",
password:"",
});
};
return (
<View >
<Text style={styles.welcome}>
Welcome! Please Register Below
</Text>
<TextInput style={styles.input} placeholder="Name" value={input.fullName} onChangeText={inputHandler}/>
<TextInput style={styles.input} placeholder="Email" value={input.email} onChangeText={inputHandler}/>
<TextInput style={styles.input} placeholder="Password" value={input.password} onChangeText={inputHandler} />
<View style={styles.button}>
<Button title="Register" onPress={registerUser} />
</View>
<View style={styles.button}>
<Button title="Already Registered? Click here to login" onPress={()=> register()} />
</View>
</View>
);
}
const styles = StyleSheet.create({
welcome:{
padding:10
},
input: {
flex: 1,
justifyContent: 'center',
backgroundColor: '#ecf0f1',
padding: 8,
borderColor:'black',
borderWidth: 2,
margin:3
},
button:{
margin:5
}
});```
I have tried this.input.fullName in the value prop but that give me an error as that is not the way i defined it with my handlers. I also could go back to just using seperate states for each input like [name,setName] [password,setPassword] ect... but I would really like to understand where my knowledge is lacking for utilizing TextInput to pass user information and storing it.
From looking through similar stackoverflow questions I also tried changing my onChangeText to this
`onChangeText={(t) =>inputHandler(t)}`
but that also doesnt solve it
Thanks!
Text is not displayed, because you react on changes, but not change state properly. onTextChanges callback return to you only text (as string), not as Event. If you need track Event you can use onChange callback.
But, I recommend to you write your logic as clean and simple as possible.
Firstly, you should separate inputHandler to independent text changes functions, because it easily to manage for now in your case. For example:
const onNameChanges = (text) => {
setInput(prev => ({
...prev,
fullName: text
}))
}
And then just assign it to props of your TextInput
<TextInput style={styles.input} placeholder="Name" value={input.fullName} onChangeText={onNameChanges}/>
That's it. You code works as expected. I prepared working example for you here
https://snack.expo.dev/BkQi-kXr-8

How to focus TextInput after component mount ( initialize with the TextInput focused ) - React Native

How do I open a stateless component with the TextInput already in foucs?
Thank you all!
Hi TĂșlio here is the code and you can also check the live working example I've added in this link --> Snack Example
export default function App() {
const focusRef = React.useRef()
React.useEffect(() => {
if (focusRef.current) focusRef.current.focus()
},[focusRef])
return (
<View style={styles.container}>
<TextInput
placeholder="FirstTextInput"
returnKeyType="next"
ref={focusRef}
blurOnSubmit={false}
style={{padding:10}}
/>
</View>
);
}
If you only want the TextInput field focused on component mount, then you can use the autoFocus prop of a TextInput component
e.g.
<TextInput
autoFocus={true}
/>

React native disable submit keyboard on device if text input is empty string

Like a title, I want to disable a submit button (Search) on device's keyboard if text input is an empty string.
I creating a search bar and using TextInput.
How can I do this?
you should have 2 state (textSearch and buttonStatus) and check every onChangeText in TextInput props
here's a simple code I've used:
import React, {Component} from 'react';
import RN, {View, StyleSheet, Text} from 'react-native';
export default class History extends Component {
constructor(props) {
super(props);
this.state={
search:null,
disabledButton:true
}
}
render(){
return(
<View style={styles.container}>
<RN.TextInput
value={this.state.search}
onChangeText={(e)=>{
this.setState({search:e, disabledButton:e==""?true:false})
}}
/>
<RN.Button
title="Search"
disabled={this.state.disabledButton}
/>
</View>
)
}
}
const styles = StyleSheet.create({
container:{flex:1, justifyContent:'center', alignItems:'center'}
})
this is the first time I've provided help here, so hopefully it helps someone.
The inputText should be whatever state you use to store your text.
addItem() is whatever function name you want to execute when there are enough characters.
I wanted to require the user to type more than 1 character, so adjust to your liking.
onSubmitEditing={() => {(inputText.length < 2) ? console.log('test') : addItem()}}
<TextInput
style={styles.input}
onSubmitEditing={() => {
(inputText.length < 2) ? console.log('test') : addItem()
}}
maxLength={20}
autoCorrect={false}
onChangeText={onChangeText}
placeholder={'Scavenger Hunt Item'}
value={inputText}>
</TextInput>

how to remove underline in react native material text field

I'm using react native text field component how can i remove bottom underline in textfield
this is my code
i followed this link: https://github.com/n4kz/react-native-material-textfield
constructor(props) {
super(props);
this.state = {
userName:'',
password:''
}
}
componentWillMount() {
}
componentDidMount(){
}
render() {
//let { userName } = this.state;
let { password } = this.state;
return (
<View style={{flex:1,justifyContent:'center'}}>
<View style={{flex:0.2,justifyContent:'center',flexDirection:'row'}}>
<View style={{flex:12}}></View>
<View style={{flex:76,borderWidth:1,borderColor:'black',borderRadius:5,marginBottom:13.7}}>
<TextField style={{ color: 'black',borderColor:'transparent'}}
label='Phone number'
textColor={'black'}
value={this.state.userName}
labelHeight={40}
labelPadding={8}
padding={10}
Bottom padding= {10}
Top padding={4}
//width={50}
//borderColor={'black'}
// textFocusColor={'orange'}
//underlineColorAndroid='transparent'
baseColor={"black"}
labelHeight={32}
blurOnSubmit={true}
//characterRestriction={10}
onChangeText={(data) => this.setState({ userName: data })}
/>
</View>
)
}
You can try underlineColorAndroid='rgba(0,0,0,0)'
Hope it helps
Other TextInput properties will also work
Ref: https://github.com/n4kz/react-native-material-textfield
React native material text field component (<TextField />) can also use all of the properties from text input component (<TextInput />). So, you can remove the underline border using underlineColorAndroid props. Set this prop to be transparent.
<TextField underlineColorAndroid="transparent" />
Try this: lineWidth={0} if you want to hide the default underline and if you want to hide the line after which appears after click try this: activeLineWidth={0}.
Fine, after using this library I end up with this solution:
You can use one of the props of react-native-material-textfield activeLineWidth with 0 as an argument.
underlineColor="transparent"

Click listener in flatlist

How can I add click listener in Flatlist?
My code:
renderItem({item, index}){
return <View style = {{
flex:1,
margin: 5,
minWidth: 170,
maxWidth: 223,
height: 304,
maxHeight: 304,
backgroundColor: '#ccc',
}}/>
}
render(){
return(<FlatList
contentContainerStyle={styles.list}
data={[{key: 'a'}, {key: 'b'},{key:'c'}]}
renderItem={this.renderItem}
/>);
}
}
Update 1: I used button but it is not working in Flatlist. However using only button instead of Flatlist, it works. Why is it not working in Flatlist renderItem?
_listener = () => {
alert("clicked");
}
renderItem({item, index}){
return<View>
<Button
title = "Button"
color = "#ccc"
onPress={this._listener}
/>
</View>
}
I used TouchableWithoutFeedback. For that, you need to add all the renderItem elements (i.e your row) into the TouchableWithoutFeedback. Then add the onPress event and pass the FaltList item to the onPress event.
import {View, FlatList, Text, TouchableWithoutFeedback} from 'react-native';
render() {
return (
<FlatList style={styles.list}
data={this.state.data}
renderItem={({item}) => (
<TouchableWithoutFeedback onPress={ () => this.actionOnRow(item)}>
<View>
<Text>ID: {item.id}</Text>
<Text>Title: {item.title}</Text>
</View>
</TouchableWithoutFeedback>
)}
/>
);
}
actionOnRow(item) {
console.log('Selected Item :',item);
}
You need to wrap your row element (inside your renderItem method) inside <TouchableWithoutFeedback> tag. TouchableWithoutFeedback takes onPress as it's prop where you can provide onPress event.
For TouchableWithoutFeedback refer this link
I used TouchableOpacity. and it's working great.This will give you click feedback. which will not be provided by TouchableWithoutFeedback. I did the following:
import { View, Text, TouchableOpacity } from "react-native";
.
.
.
_onPress = () => {
// your code on item press
};
render() {
<TouchableOpacity onPress={this._onPress}>
<View>
<Text>List item text</Text>
</View>
</TouchableOpacity>
}
If you are facing flatlist row first click issue
please add below property to flatlist.
disableScrollViewPanResponder = {true}
The Pressable component is now preferred over TouchableWithoutFeedback (and TouchableOpacity). According to the React Native docs for TouchableWithoutFeedback:
If you're looking for a more extensive and future-proof way to handle touch-based input, check out the Pressable API.
Example implementation:
import { Pressable } from "react-native";
render() {
return(
<FlatList
contentContainerStyle={styles.list}
data={[{key: 'a'}, {key: 'b'}, {key:'c'}]}
renderItem={({item}) => (
<Pressable onPress={this._listener}>
// BUILD VIEW HERE, e.g. this.renderItem(item)
</Pressable>
)}
/>
);
}
References
TouchableWithoutFeedback (React Native): https://reactnative.dev/docs/touchablewithoutfeedback
Pressable (React Native): https://reactnative.dev/docs/pressable
you dont need to add Touchable related component into your Flatlist renderItem. Just pass onTouchStart prop to your Flatlist.
in example:
<FlatList
style={themedStyles.flatListContainer}
data={translations}
renderItem={renderItem}
keyExtractor={(item, index) => `${item.originalText}____${index}`}
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
ListEmptyComponent={renderEmptyListComponent}
onTouchStart={onBackgroundPressed}
/>