react native, how to paste text from clipboard into text input - javascript

currently i am using native base and having this type of text input for search bar
<Text>
Card Name
</Text>
<Header searchBar rounded style={{ backgroundColor: '#E9E9EF'}}>
<Item style={{ backgroundColor: 'lightgray', borderRadius: 5 }}>
<Icon name="ios-search" />
<Input placeholder="Search" onChangeText={(searchText) => this.setState({searchText})} value={this.state.searchText} />
</Item>
</Header>
I wanted to enable paste from clipboard, where user can copy some text from other places and paste it on this search input box. How can i do that?

You can use the clipboard API : https://facebook.github.io/react-native/docs/clipboard
or Textinput property : selectTextOnFocus
<TextInput selectTextOnFocus={true} />

If copy/paste not working for TextInput in react native. you can follow this code.
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({ textboxWidth: '100%' })
}, 100)
}
render() {
return (
<View style={{ marginTop: 40 }}>
<TextInput
style={{ width: this.state.textboxWidth }}
placeholder="Please type"
onChangeText={(text) => this.setState({ text })}
value={this.state.text}
/>
</View>
);
}
}

The solution found in this Git reply worked much better for me: 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>

user RN gesture handler's TextInput instead of react native's
import {TextInput} from 'react-native-gesture-handler';
do add the following
selectTextOnFocus={true}
to the TexInput

You can use this community package which is suggested by the official docs
#react-native-clipboard/clipboard
import Clipboard from '#react-native-clipboard/clipboard'
You can easily access clipboard text by invoking an async function
const text = await Clipboard.getString()

This is parameter in TextInput secureTextEntry={true} works

Related

How to change props of TextInput component in a FlatList?

I'm a newbie in React Native.
What I'm trying to do is making a Google Maps-like app. At the MainMap.js screen, when we enter,the screen will immediately generate 2 search bars. The first one will have the text "Your location". The second one and so on will be empty for users to type in for searching location.
But, I'm having some problems with the FlatList component. In my PlaceInput component, I use the defaultValue, as a prop, for the text input. And then in the MainMap.js, I will have a state which initially be set as "Your Location", then I'll change it to null when the FlatList starts rendering from the 2nd PlaceInput component.
Here's the MainMap.js*
import React from 'react';
import {
TouchableWithoutFeedback,
StyleSheet,
Keyboard,
PermissionsAndroid,
Platform,
View,
Button,
FlatList,
Dimensions
} from 'react-native';
import PlaceInput from '../components/PlaceInput';
import axios from 'axios';
import PolyLine from '#mapbox/polyline';
import MapView, {Polyline, Marker} from 'react-native-maps';
import Geolocation from 'react-native-geolocation-service';
const INCREMENT = 1;
const HEIGHT = Dimensions.get('window').height;
const WIDTH = Dimensions.get('window').width;
class MainMap extends React.Component{
constructor(props){
super(props);
this.state={
_userLocationDisplayed: null,
userLatitude: 0,
userLongitude: 0,
numOfInput:[0,1],
counter: 1,
};
};
componentDidMount(){
this._requestUserLocation();
};
// Get user current location
// Ask user permission for current location
// Request the Directions API from Google
// Get the formatted_address & name from Google Places API
// Adding a search bar
onAddSearch(){
this.setState((state) => ({
counter: state.counter + INCREMENT,
numOfInput: [...state.numOfInput, state.counter],
}));
};
onChangeSearchDisplay(){
this.setState({
_userLocationDisplayed: null
})
};
render(){
return(
<TouchableWithoutFeedback onPress={this.hideKeyboard} >
<View style={styles.container} >
<View style={{height: HEIGHT/2.5 }}>
<FlatList
data={this.state.numOfInput}
keyExtractor={(item, index) => item}
renderItem={itemData => {
return(
<PlaceInput
id={itemData.item}
onDelete={this.onDeleteSearch}
showDirectionOnMap={this.showDirectionOnMap}
userLatitude={userLatitude}
userLongitude={userLongitude}
userLocationDisplayed={this.state._userLocationDisplayed}
/>
)
}}
/>
</View>
</View>
</TouchableWithoutFeedback>
)
}
}
//}
export default MainMap;
const styles = StyleSheet.create({
container:{
flex: 1
},
map:{
...StyleSheet.absoluteFillObject
},
});
Here's the PlaceInput component
import React from 'react';
import {
View,
TextInput,
StyleSheet,
Text,
Dimensions,
TouchableOpacity,
Keyboard,
} from 'react-native';
import axios from 'axios';
import _ from 'lodash'
import Icon from 'react-native-vector-icons/MaterialCommunityIcons'
const WIDTH = Dimensions.get('window').width;
const HEIGHT = Dimensions.get('window').height;
class PlaceInput extends React.Component{
constructor(props){
super(props);
this.state={
...
}
...
}
render() {
// console.log(this.state);
// Code for displaying the suggestions from the Google Place API
// Don't care about it too much :)))
const predictions = this.state.predictions.map(prediction => {
const { id, structured_formatting, place_id } = prediction;
return(
<TouchableOpacity
key={id}
onPress={() => this.setDestination(structured_formatting.main_text, place_id)}
>
<View style={styles.suggestion}>
<Text style={styles.mainText}>{structured_formatting.main_text}</Text>
<Text style={styles.secText}>{structured_formatting.secondary_text}</Text>
</View>
</TouchableOpacity>
);
} )
return (
<View style={{flex: 1, flexDirection: 'column'}} key={this.props.id}>
<View style={styles.buttonContainer}>
<View style={{flex: 1, alignItems: 'center'}}>
<Text style={{fontSize: 8}}>{'\u25A0'}</Text>
</View>
<View style={{flex: 4}}>
<TextInput
key={this.id}
autoCorrect={false}
autoCapitalize='none'
style={styles.inputStyle}
placeholder='Search your places'
onChangeText={(input) => {
this.setState({destinationInput: input});
this.getPlacesDebounced(input);
}}
value={this.state.destinationInput}
{/*What I'm trying here as mentioned*/}
defaultValue={this.props.userLocationDisplayed}
/>
</View>
<View style={styles.rightCol}>
<TouchableOpacity onPress={() => this.props.onDelete(this.props.id)}>
<Icon name='delete' size={25} style={{alignSelf: 'center'}} />
</TouchableOpacity>
</View>
</View>
{predictions}
</View>
)
}
}
const styles = StyleSheet.create({
buttonContainer:{
flexDirection: 'row',
height: (HEIGHT - 690),
width: (WIDTH-48),
marginTop: 55,
padding: 5,
backgroundColor: 'white',
shadowColor: '#000000',
elevation: 7,
shadowRadius: 5,
shadowOpacity: 1,
borderRadius: 5,
alignItems: 'center',
alignSelf:'center'
},
inputStyle:{
fontFamily: 'sans-serif-thin',
fontSize: 16,
color: 'black',
fontWeight: 'bold'
},
suggestion:{
backgroundColor: 'white',
padding: 10,
borderWidth: 0.5,
width: (WIDTH-48),
alignSelf: 'center'
},
secText:{
color: '#777'
},
mainText:{
color: '#000'
},
rightCol:{
flex: 1,
borderLeftWidth: 1,
borderColor: '#ededed',
},
})
export default PlaceInput;
I'd love to hear your comments for helping me.
Also, feel free to give out other ways too since I think my way isn't optimized enough. And I'm building this for production too.
If I understand your question correctly, you're asking how to conditionally set a prop value based upon where it is in the flatlist data. Basically you want the first PlaceInput component to have a displayed "entered" text value of "Your Location" and the rest to have nothing.
Update API of PlaceInput to take in another prop to indicate displaying a default value or not.
PlaceInput.js
...
<TextInput
key={this.id}
autoCorrect={false}
autoCapitalize='none'
style={styles.inputStyle}
placeholder='Search your places'
onChangeText={(input) => {
this.setState({destinationInput: input});
this.getPlacesDebounced(input);
}}
value={this.state.destinationInput}
defaultValue={this.props.displayDefaultValue ? this.props.defaultValue : null}
/>
...
And pass in whether or not any specific PlaceInput should display it or not. Since you want only the first to display and the rest to not, using the array index is a good place to start. Here we can leverage the fact that in javascript 0 is a falsey value, while all other numbers are truthy. Using !index then !0 is true while !1, !2, etc, are all false.
MainMap.js
<FlatList
data={this.state.numOfInput}
keyExtractor={(item, index) => item}
renderItem={({ index, item }) => {
return(
<PlaceInput
id={item}
defaultValue="Your Location"
displayDefaultValue={!index} // index 0 is falsey, all others truthy
onDelete={this.onDeleteSearch}
showDirectionOnMap={this.showDirectionOnMap}
userLatitude={userLatitude}
userLongitude={userLongitude}
userLocationDisplayed={this.state._userLocationDisplayed}
/>
)
}}
/>
I take advantage of Drew Reese's answer but It doesn't work
I found out why it doesn't work because of the value prop, whose value is set by this.state.destinationInput which is " " in the state in the constructor. I again use Drew's way in the value prop instead, and it works
<TextInput
key={this.id}
autoCorrect={false}
autoCapitalize='none'
style={styles.inputStyle}
placeholder='Search your places'
onChangeText={(input) => {
this.setState({destinationInput: input});
this.getPlacesDebounced(input);
}}
value={this.props.displayDefaultValue ? this.props.defaultValue : this.state.destinationInput}
/>
BIG thanks to Drew Reese

React Native - Show keyboard and render its values without using an input

Is there a way to use a keyboard only without any text input and get its values onChange?
I would like to show the keyboard only on button click event and render its typing values in a view without any input.
What would be a correct way of implementing this?
You can add a dummy TextInput and onPress button set focus on TextInput to show keyboard . Save state with "onChangeText" prop and show in a View
Complete Code
import React from "react";
import { View, Text, Button, TextInput } from "react-native";
export default class App extends React.Component {
state = { text: "" };
render() {
return (
<View style={{ flex: 1, marginTop: 50 }}>
<TextInput
style={{ height: 0, width: 0, borderWidth: 0 }}
onChangeText={text => this.setState({ text })}
ref={ref => {
this.textInput = ref;
}}
autoCapitalize="none"
autoCorrect={false}
autoFocus={false}
/>
<Button
onPress={() => {
this.textInput.focus();
}}
title="Press Me To show Keyboard"
color="#841584"
/>
<View
style={{
borderColor: "red",
borderWidth: 1,
padding: 16,
marginTop: 20
}}
>
<Text style={{ marginBottom: 8 }}>Show Typing Values:</Text>
<Text>{this.state.text}</Text>
</View>
</View>
);
}
}
App Preview

KeyboardAvoidingView collapses all inner components when contains one View

When using KeyboardAvoidingView with behavior="position" property and if that KeyboardAvoidingView component contains one View with multiple items in it, all inner components are collapsed one over the other, as if flex == 0 for all of them:
Example 1
Here is an example (Input is a react-native-elements component based on TextInput):
return (
<KeyboardAvoidingView
behavior="position"
style={{
flex: 1
}}
>
<View style={{ flex: 1, paddingTop: 50 }}>
<Input
value={email}
keyboardAppearance="light"
autoFocus={false}
autoCapitalize="none"
autoCorrect={false}
keyboardType="email-address"
returnKeyType="next"
placeholder={"Email"}
containerStyle={{
marginLeft: 10
}}
errorMessage={
!isEmailValid
? "Please enter a valid email address"
: undefined
}
/>
<Input
value={password}
keyboardAppearance="light"
autoCapitalize="none"
autoCorrect={false}
secureTextEntry={true}
returnKeyType={"done"}
blurOnSubmit={true}
containerStyle={{
marginLeft: 10
}}
placeholder={"Password"}
errorMessage={
isEmailValid && !isPasswordValid
? "Please enter at least 8 characters"
: undefined
}
/>
</View>
</KeyboardAvoidingView>)
If I change the property to behavior="padding" it becomes fine as expected, but I am not interested in "padding" behavior.
Hope it is what you expected.
import React, { Component } from 'react';
import {
Text,
View,
StyleSheet,
KeyboardAvoidingView,
TextInput,
ScrollView
} from 'react-native';
import { Constants } from 'expo';
import { Input } from 'react-native-elements';
export default class App extends Component {
render() {
const email = '';
const password = '';
return (
<ScrollView >
<KeyboardAvoidingView
behavior="position"
style={{
flex: 1,
paddingTop: 50
}}>
<Input
value={email}
placeholder={'Email'}
/>
<Input
value={password}
placeholder={'Password'}
/>
</KeyboardAvoidingView>
</ScrollView>
);
}
}
Here is expo snack https://snack.expo.io/rkPA0C00f
Eventually I got tired from trying to get KeyboardAvoidingView to work as expected and I was able to achieve what I needed using react-native-keyboard-aware-scroll-view which is a simple and powerful library.
Here's a code sample:
import React, { Component } from 'react';
import {
Text,
View,
StyleSheet,
KeyboardAvoidingView,
TextInput,
ScrollView
} from 'react-native';
import { Constants } from 'expo';
import { Input } from 'react-native-elements';
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
export default class App extends Component {
render() {
const email = '';
const password = '';
return (
<KeyboardAwareScrollView
style={{
flex: 1
}}
scrollEnabled={false}>
<Input
value={email}
placeholder={'Email'}
/>
<Input
value={password}
placeholder={'Password'}
/>
</KeyboardAwareScrollView>
);
}
}
Thanks for the help Aung Myat Hein.
<KeyboardAvoidingView
behavior={'position'}
keyboardVerticalOffset={Platform.OS === 'ios' ? 0 : 24}
>

ReactNative TextInput not letting me type

For both iOS and Android simulators
The text just disappears/flickers when I start typing. I tried having an initial state of texts with some value instead of keeping it empty. With this the TextInput sticks to this initial state and does not update itself with new text entered.
I think the state is not updating with 'onChangeText' property, but I am not completely sure.
People have seem to solve this, as they had few typos or missing pieces in code. However I have checked mine thoroughly.
Please help if I have missed anything in the below code.
LoginForm.js
import React, { Component } from 'react';
import { Card, Button, CardSection, Input } from './common';
class LoginForm extends Component {
state = { email: '', password: '' }
render() {
return (
<Card>
<CardSection>
<Input
label="Email"
placeHolder="user#gmail.com"
onChangeText={text => this.setState({ email: text })}
value={this.state.email}
/>
</CardSection>
<CardSection>
<Input
secureTextEntry
label="Password"
placeHolder="password"
onChangeText={text => this.setState({ password: text })}
value={this.state.password}
/>
</CardSection>
<CardSection>
<Button>
Log In
</Button>
</CardSection>
</Card>
);
}
}
export default LoginForm;
Input.js
import React from 'react';
import { TextInput, View, Text } from 'react-native';
const Input = ({ label, value, onChangeText, placeholder, secureTextEntry }) => {
const { inputStyle, labelStyle, containerStyle } = styles;
return (
<View style={containerStyle}>
<Text style={labelStyle}>{label}</Text>
<TextInput
secureTextEntry={secureTextEntry}
placeholder={placeholder}
autoCorrect={false}
style={inputStyle}
value={value}
onChangeText={onChangeText}
/>
</View>
);
};
const styles = {
inputStyle: {
color: '#000',
paddingRight: 5,
paddingLeft: 5,
fontSize: 18,
lineHeight: 23,
flex: 2
},
labelStyle: {
fontSize: 18,
paddingLeft: 20,
flex: 1
},
containerStyle: {
height: 40,
flex: 1,
flexDirection: 'row',
alignItems: 'center'
}
};
export { Input };
The only way to solve this was to change the way the values of TextInput fields are updated, with this code below.
value={this.state.email.value}
value={this.state.password.value}
You problem is how the Input component is written.
There is a render function written inside the stateless component which is not a React class component:
const Input = ({ label, value, onChangeText, placeHolder, secureTextEntry }) => ( // ← remove the wrapping parentheses
{
render() { // <--- this should not be here
↑
const { inputStyle, labelStyle, containerStyle } = styles;
return (
<View style={containerStyle} >
<Text style={labelStyle}>{label}</Text>
<TextInput
secureTextEntry={secureTextEntry}
autoCorrect={false}
placeholder={placeHolder}
style={inputStyle}
onChangeText={onChangeText}
value={value}
underlineColorAndroid="transparent"
/>
</View>
);
}
}
);
Change it to this:
const Input = ({ label, value, onChangeText, placeHolder, secureTextEntry }) => {
const { inputStyle, labelStyle, containerStyle } = styles;
return (
<View style={containerStyle} >
<Text style={labelStyle}>{label}</Text>
<TextInput
secureTextEntry={secureTextEntry}
autoCorrect={false}
placeholder={placeHolder}
style={inputStyle}
onChangeText={onChangeText}
value={value}
underlineColorAndroid="transparent"
/>
</View>
);
};
See running example

React native card (native base) onPress doesn't work

I want to display cards with news from a JSON file.
Getting the JSON works fine, but I want to add a onPress event, so I can click the card and navigate to the article.
My card view:
<Card>
<CardItem button onPress={this._OnButtonPress(news.id)}>
<Left>
<Body>
<Text style={styles.cardText}>{news.title}</Text>
</Body>
</Left>
</CardItem>
<CardItem>
<Left>
<Icon style={styles.icon} name="chatbubbles" />
<Text>{news.comments} comments</Text>
</Left>
<Right>
<Text>{news.published}</Text>
</Right>
</CardItem>
</Card>
I am trying to pass a variable to the onButtonPress() function
_OnButtonPress(newsID) {
Alert.alert(newsID.toString());
}
To test the onPress event, all I did is alert the parameter.
I don't see anything wrong, but still I got this error
Does anyone know how I can fix this and what Im doing wrong here.
Thanks in advance.
Update
My updated class:
import React, { Component } from "react";
import {
Image,
ListView,
StyleSheet,
Text,
View,
Alert
} from 'react-native';
import {
Container,
Header,
Left,
Right,
Button,
Card,
CardItem,
Icon,
Body,
Content,
Logo
} from 'native-base';
import styles from "./styles";
const logo = require("../../../img/f1today.png");
var REQUEST_URL = 'http://v2.first-place.nl/test/news.json';
class News extends Component {
constructor(props) {
super(props);
this._OnButtonPress = this._OnButtonPress.bind(this);
this.state = {
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
}),
loaded: false,
};
}
_OnButtonPress(newsID) {
Alert.alert(newsID.toString());
}
componentDidMount() {
this.fetchData();
}
fetchData() {
fetch(REQUEST_URL)
.then((response) => response.json())
.then((responseData) => {
this.setState({
dataSource: this.state.dataSource.cloneWithRows(responseData.articles),
loaded: true,
});
})
.done();
}
render() {
if (!this.state.loaded) {
return this.renderLoadingView();
}
return (
<Container style={styles.container}>
<Header
style={{ backgroundColor: "#fff" }}
androidStatusBarColor="#f05423"
iosBarStyle="light-content">
<Left>
<Button
transparent
onPress={() => this.props.navigation.navigate("DrawerOpen")}
>
<Icon name="ios-menu" style={{color: 'black'}} />
</Button>
</Left>
<Body>
<Image source={logo} style={styles.headerLogo} />
</Body>
<Right />
</Header>
<Content padder>
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderNews}
style={styles.listView}
/>
</Content>
</Container>
);
}
renderLoadingView() {
return (
<View style={styles.loading}>
<Text>
Loading news...
</Text>
</View>
);
}
renderNews(news) {
return (
<Card>
<CardItem button onPress={()=> this._OnButtonPress(news.id)}>
<Left>
<Body>
<Text style={styles.cardText}>{news.title}</Text>
</Body>
</Left>
</CardItem>
<CardItem>
<Left>
<Icon style={styles.icon} name="chatbubbles" />
<Text>{news.comments} comments</Text>
</Left>
<Right>
<Text>{news.published}</Text>
</Right>
</CardItem>
</Card>
);
}
}
export default News;
You should wrap your CardItem with TouchableOpacity or any other Touchable item. And give onPress function to that Touchable item.
<TouchableOpacity onPress={() => //your function}
<CardItem>
</CardItem>
</TouchableOpacity>
Note: Make sure you use the <TouchableOpacity> component associated with the react-native package rather than the react-native-gesture-handler package. Visual Studio Code editor may auto-import from react-native-gesture-handler which does not work in this particular use case.
Correct Package:
import { TouchableOpacity } from 'react-native';
Incorrect Package:
import { TouchableOpacity } from 'react-native-gesture-handler';
For me i left the button={true} prop off, when i added it works. See example below.
<CardItem
button={true}
onPress={() => {this.cardSelected(item.name)}}
style={{paddingTop:0,paddingBottom:0,paddingLeft:0,paddingRight:0}}>
<Image source={item.img} style={{flex:1,resizeMode: 'cover',height: 175}} />
<Text style={styles.cardheading}>{item.name}</Text>
<Image source={cardline} style={styles.cardline}/>
<Text style={styles.cardtext}> {item.text}</Text>
</CardItem>
The problem you are having is that the method cannot access the scope of the view. Right now you have your renderNews method defined this way:
renderNews(news) { }
If you declare your method this way you will not have this available on your method and as "this" is undefined, all the methods will trigger an error because you are trying to access to "undefined.methodName()". Having said that, you should "tie" the context to your method declaring it this way:
renderNews = (news) => { }
Now you have the context attached to the method and "this" is accesible inside.
You need to bind this function. Write the following code inside your constructor function:
this._OnButtonPress = this._OnButtonPress.bind(this);
Also, changed the onPress as following:
onPress={()=> this._OnButtonPress(news.title)}
Finally, i could see the onPress been written on the component. Rather you should define/write it inside that container.

Categories

Resources