how can i operate onBlur event in react-native? - react-native

I'm trying to develop a search app using expo react-natvie.
<TextInput
placeholder="placeholder"
onBlur={() => console.log('blur')}
onFocus={() => console.log('focus')}
/>
in this code, onFocus is working.
but, onBlur is not working.
i think "i clicked other text, so onBlur event will work"
but, still focus.
how can i operate onBlur event?
i add my code
import { View, TextInput, TouchableOpacity } from 'react-native';
const App = () => {
return (
<View style={{ borderWidth: 1, height: 1000, backgroundColor: 'gray' }}>
<TextInput
onBlur={() => console.log('blur1')}
onEndEditing={() => console.log('blur2')}
onFocus={() => console.log('focus')}
style={{ marginTop: 40, borderWidth: 1 }}
/>
<TouchableOpacity style={{ height: 600 }} onPress={() => console.log('press')} />
</View>
);
};
export default App;
first, i clicked textinput. the onFocus event is work.
second, i clicked out. TouchableOpacity onPress event is work, but Textinput onBlur is not work...

You can try using the onEndEditing prop on the TextInput component.
<TextInput
placeholder="placeholder"
onEndEditing={() => console.log('blur')}
onFocus={() => console.log('focus')}
/>

Related

How to create outlined (focused) TextInput in React Native?

Here is my code:
<View style={styles.inputView} >
<TextInput
style={styles.TextInputStyleClass}
placeholder="Email"
placeholderTextColor="#003f5c"
onChangeText={text => this.setState({email:text})}/>
</View>
Here is textinput style
TextInputStyleClass:{
textAlign: 'auto',
height: 50,
borderWidth: 1,
borderColor: '#c2c2c2',
borderRadius: 5 ,
backgroundColor : "#ffffff"
}
I am new to React Native application development and I am trying to textinput outlined focus. But the textinput is not focused with the code which I wrote above. Also I have tried with textinput mode but nothing helped me.
How can I create textInput outlined focus?
try to use component state.
class textInput extends React.Component {
constructor(props) {
super(props);
this.state = { isFocus: false };
}
render() {
return (
<TextInput
onBlur={() => {
this.setState({ isFocus: false });
}}
onFocus={() => {
this.setState({ isFocus: true });
}}
style={this.isFocus ? { borderColor: 'red' } : { borderColor: 'green' }}
/>
);
}
}
you should add the mode='outlined'
<View style={styles.inputView} >
<TextInput
style={styles.TextInputStyleClass}
placeholder="Email"
mode='outlined'
placeholderTextColor="#003f5c"
onChangeText={text => this.setState({email:text})}
/>
</View>

How to programmatically call the onPress() method of Pressable?

I want to call the onPress() method of my Pressable. How can I achieve this? I tried calling the onPress() method when I hit the second button via a ref but it did not work.
const pressableRef = useRef(null);
return (
<Pressable
style={{ width: 100, height: 100, backgroundColor: 'yellow' }}
onPress={() => console.log('I want to print this')}
ref={pressableRef}
/>
<Button
title="Klick me"
onPress={() => {pressableRef.current.onPress()}
/>
);
There is no method with the name onPress on Pressable Component that you can call by reference. onPress is a prop you pass to the Pressable that accepts a function.
You can define a function before return so it can be available by both.
Try this
const callPressableFunc = () => {
console.log('I want to print this');
};
return (
<View>
<Pressable
style={{width: 100, height: 100, backgroundColor: 'yellow'}}
onPress={callPressableFunc}
ref={pressableRef}
/>
<Button title="Klick me" onPress={callPressableFunc} />
</View>
);
my code not work in this situation, but i do some changes and it works for me :)
this is my code:
const ElementRef = createRef();
useEffect(() => {
if (ElementRef.current) {
setTimeout(() => {
ElementRef.current?.scrollToIndex({
index: 3,
animated: true
})
}, 500);
}
}, [ElementRef])
// ...
<FlatList
nestedScrollEnabled
data={Calendar}
keyExtractor={item => item.visit_day_identity}
renderItem={renderItem}
horizontal
showsHorizontalScrollIndicator={false}
snapToEnd
ref={ElementRef}
/>

Render a component onPress(TouchableOpacity/Button) in React Native

I have a functional that has a fetch call to Wordnik Api and it returns one random word. It works all fine, but am trying to set up a TouchbaleOpacity/Button that will render that component onPress so I can get a random word every time the user clicks on the button. I have the other component in a separate file, how do call it on button Press?
`export default function HomeScreen({ navigation }) {
const onPress = () => {
//return component
};
return (
<View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
<TouchableOpacity onPress={onPress}>
<Button title="Next word" />
</TouchableOpacity>
<Wordnik />
</View>
);
}`
Add a props key on your component and change that key every time on your button's onPress so component will render every time when key change as following :
export default function HomeScreen({ navigation }) {
const [tempKey, setTempKey] = useState(0);
const onPress = () => {
//return component
setTempKey(tempKey+1);
};
return (
<View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
<TouchableOpacity onPress={onPress}>
<Button title="Next word" />
</TouchableOpacity>
<Wordnik key={tempKey.toString()} />
</View>
);
}

Enable paste and selection within TextInput - React Native

I am trying to implement copy and paste within my TextInput but cant seem to achieve it. I was expecting a tooltip when I long-pressed on my TextInput, however nothing happens.
I know about Clipboard and would know how to implement it, but I cant seem to get the paste option to pop to the user.
Any ideas how I can achieve this?
<TextInput
maxLength={29}
autoCapitalize={'characters'}
numberOfLines={1}
keyboardType={'default'}
underlineColorAndroid='transparent'
autoCorrect={false}
value={IBAN.printFormat(this.state.ibanInput)}
returnKeyType={'next'}
onChangeText={iban => this.verifyIban(iban)}
style={[{ borderWidth: 1, borderRadius: 2, height: '100%', width: '100%', textAlign: 'center', fontSize: width/24 },
]}
/>
Here is the answer if copy/paste does not work for TextInput - React Native
Step 1) In Contructor take testWidth property and assign value as '99%'.
e.g.
this.state = {testWidth: '99%' };
Step 2) In componentDidMount change testWidth value like '100%', do it inside of setTimeout.
e.g.
setTimeout(() => {
this.setState({ testWidth: '100%' })
}, 100)
Step 3) In style attribute of TextInput add dynamic width which we declare in Contractor, e.g
<TextInput style={{ width: this.state.testWidth }} />
Here is the full code: (Just copy and paste in App.js file).
import React, { Component } from 'react';
import { TextInput, View } from 'react-native';
export class App extends Component {
constructor(props) {
super(props);
this.state = { text: '', testWidth: '99%' };
}
componentDidMount() {
setTimeout(() => {
this.setState({ testWidth: '100%' })
}, 100)
}
render() {
return (
<View style={{ marginTop: 50 }}>
<TextInput
style={{ width: this.state.testWidth }}
placeholder="Type here to translate!"
onChangeText={(text) => this.setState({ text })}
value={this.state.text}
/>
</View>
);
}
}
Good Luck
Have a look at this code!: https://github.com/facebook/react-native/issues/18926#issuecomment-490541013
<ScrollView
contentContainerStyle={Styles.contentContainerStyle}
keyboardShouldPersistTaps="handled"
removeClippedSubviews={false}>
<KeyboardAvoidingView>
<Text style={Styles.labelPageTitle}>
{'bla bla bla'}
</Text>
<Text>
{'bla bla bla'}
</Text>
<TextInput
onChangeText={text => this.setState({ title: text })}
style={Styles.textInput}
value={title}
/>
</KeyboardAvoidingView>
use RN-clipboard
const text = await Clipboard.getString()
setCopiedText(text)

How would I grow <TextInput> height upon text wrapping?

I'm trying to create a <TextInput> that can grow in height when the text wraps to the next line, similar to how Slack's message input grows with the text up to a point.
I have the multiline prop set, so it is wrapping but the docs don't seem to mention any event regarding wrapping, and the only thing I can think of is a really hacky strategy to character count to figure out when to increase height of the input. How would I accomplish this?
https://facebook.github.io/react-native/docs/textinput.html
Thanks to react-native doc: https://facebook.github.io/react-native/docs/textinput.html
You can do something like that:
class AutoExpandingTextInput extends React.Component {
state: any;
constructor(props) {
super(props);
this.state = {text: '', height: 0};
}
render() {
return (
<TextInput
{...this.props}
multiline={true}
onChange={(event) => {
this.setState({
text: event.nativeEvent.text,
height: event.nativeEvent.contentSize.height,
});
}}
style={[styles.default, {height: Math.max(35, this.state.height)}]}
value={this.state.text}
/>
);
}
}
0.46.1 or higher: (as explained by Nicolas de Chevigné)
class AutoExpandingTextInput extends React.Component {
constructor(props) {
super(props);
this.state = {text: '', height: 0};
}
render() {
return (
<TextInput
{...this.props}
multiline={true}
onChangeText={(text) => {
this.setState({ text })
}}
onContentSizeChange={(event) => {
this.setState({ height: event.nativeEvent.contentSize.height })
}}
style={[styles.default, {height: Math.max(35, this.state.height)}]}
value={this.state.text}
/>
);
}
}
Since React Native 0.46.1 :
contentSize property was removed from TextInput.onChange event
If you use this version, you can deal with onContentSizeChange prop
From the Jérémy answer, we have
class AutoExpandingTextInput extends React.Component {
constructor(props) {
super(props);
this.state = {
text: '',
height: 0
};
}
render() {
return (
<TextInput
{...this.props}
multiline={true}
onChangeText={(text) => {
this.setState({ text })
}}
onContentSizeChange={(event) => {
this.setState({ height: event.nativeEvent.contentSize.height })
}}
style={[styles.default, {height: Math.max(35, this.state.height)}]}
value={this.state.text}
/>
);
}
}
You should just set a maxHeight property in the style:
<TextInput multiline style={{maxHeight: 80}} />
Demo here: https://snack.expo.io/#yairopro/multiline-input-with-max-height
My answer is to use onContentSizeChange and numberOfLines props in TextInput, of course turn on multiline, this is my solution:
let numOfLinesCompany = 0;
<TextInput
...
multiline={true}
numberOfLines={numOfLinesCompany}
onContentSizeChange={(e) => {
numOfLinesCompany = e.nativeEvent.contentSize.height / 18;
}}
/>
18 is the height of text, propably depends on fontSize
Shoutout to Jérémy Magrin for his answer. This is his code but refactored to use functional components and hooks.
Note, you might need to use minHight instead of height in some RN versions.
const AutoExpandingTextInput = ({...props})=> {
const [text, setText] = useState('');
const [height, setHeight] = useState();
return (
<TextInput
{...props}
multiline={true}
onChangeText={text => {
setText(text);
}}
onContentSizeChange={event => {
setHeight(event.nativeEvent.contentSize.height);
}}
style={[styles.default, {height: height}]}
value={text}
/>
);
}
<TextInput multiline style={{maxHeight: ...}} />
In the hooks.
const [inputHeight, setInputHeight] = React.useState(40);
<TextInput
multiline
style={{ inputHeight }}
onContentSizeChange={(event) => {
setInputHeight(event.nativeEvent.contentSize.height);
}}
/>
What I have done is set View for the Input max height, for example:
messageBox: {
maxHeight: 110,
width: '80%',
borderRadius: 10,
padding: 10,
backgroundColor: Color.White},
and set the Input to multiline:
<View style={[styles.messageBox, styles.managerMsg]}>
<Input
allowFontScaling={false}
name="notes"
blurOnSubmit={false}
onChangeText={notes => console.log(notes)}
returnKeyType="go"
onSubmitEditing={() => Keyboard.dismiss()}
multiline
/>
</View>
This "Input" is just a simple custom component that receives all Props.
You might as well try something like this.
<TextInput style={[styles.inputs,{height: Math.max(35, this.state.height)}]}
placeholder="Write a message..."
multiline={true}
onChangeText={(msg) => this.setState({ text: msg })}
onSubmitEditing={Keyboard.dismiss}
onContentSizeChange = {() => this.scrollView.scrollToEnd({animated:true})}
/>
style.inputs
inputs: {
minHeight:40,
marginLeft: 16,
paddingTop: 10,
overflow:'hidden',
padding: 15,
paddingRight: 25,
borderBottomColor: '#000000',
flex: 1,
position: 'absolute',
width: '100%',
},
When the text grows beyond one line, a scroll view is created within the text input field and scrolls automatically to the bottom. This actually doesn't increase the text input height when the content grows, instead, a scroll view is created within the input field. Serves the purpose.
I'm posting my solution as others didn't work for me(the text input size grew behind the keyboard, and there were text-overflow issues).
Hence, for anyone who faced a similar problem as I did, this would hopefully work for you.
<View style={{flex:1}}>
<TextInput
multiline={true} />
</View>
You can also use onChangeText to set the TextInput height like so.
const textHeight = 19 //fontsize of the text
<TextInput
style={[styles.input,
{height:Math.max(40,inputHeight)}]}
onChangeText= {text => {
const height = text.split("\n").length
setInputHeight(height * textHeight)
}}
multiline
/>
Just use multiline={true} no need to set height. check the following
<SafeAreaView style={{flex:1, backgroundColor:"#F8F8F9"}}>
<ScrollView style={{flex:1}}>
{
this.state.data && <CommentListView data={this.state.data} onReplyClick={this.onReplyClick}/>
}
</ScrollView>
<View style={{bottom:Platform.OS=="ios" ? this.state.keyboardHeight : 0, flexDirection:"row", alignItems:"flex-end", padding:10}}>
<TextInput
multiline={true}
style={{flex:3, backgroundColor:"#EFEFEF", borderRadius:5, padding:10}}
value={this.state.comment}
onChangeText={(text)=> this.setState({comment:text})}
/>
<TouchableOpacity style={{flex:1}} onPress={()=> this.submit()}>
<Text style={{padding:13, color:"#fff", textAlign:"center", fontWeight:"bold", backgroundColor:"#00394D", borderWidth:1, borderColor:"#00FFEE", borderRadius:5, overflow: "hidden"}}>Post</Text>
</TouchableOpacity>
</View>
</SafeAreaView>