TextInput clear text on icon press not clearing - javascript

I want to set the value of my custom TextInput to "" when the iconPress is called.
The problem is, that when i call the iconPress, it should clear the text of my TextInputCode field.
But it isnt updated on my screen, isnt clearing the input field.
But it just doesnt change the value/clear it...
This is my code:
const [searchString, setSearchString] = useState("");
const submitHandler = () => {
setSearchString("")}
const changeHandler = (value) => {
setSearchString(value)}
return(...
<TextInputCode
value={searchString}
onChange={(text) => {
changeHandler(text);}}
iconType={
Platform.OS === "android"
? isSearchbarFocused
? "chevron-left"
: "search"
: "search"
}
iconPress={() => {
Platform.OS === "android" && isSearchbarFocused
? (submitHandler(), setSearchbarFocused(false), Keyboard.dismiss())
: "keine suche";
}}
showCancel
placeholderTextColor={colors.text}
onFocus={() => {
setSearchbarFocused(true);
}}
/>
...)
This is the code of my TextInputCode element, but I dont think that this is the problem:
const TextInputCode = ({
iconType,
placeholder,
onChange,
onFocus,
textContentType,
autoCapitalize,
autoCompleteType,
iconPress,
onClear
}) => {
return (
<View style={styles.inputView}>
<Icon name={iconType} onPress={iconPress} size={20}
/>
<TextInput
style={{
flex: 1,
paddingHorizontal: 12,
}}
placeholder={placeholder}
textContentType={textContentType}
autoCapitalize={autoCapitalize}
autoCompleteType={autoCompleteType}
autoCorrect={false}
onChangeText={(e) => onChange(e)}
onFocus={onFocus}
onClear = {onClear}
/>
</View>
);
};
I dont understand why this isnt working. What am I doing wrong?

Related

Passing text as param in textinput react native

<TextInput
ref={(ref) => (this.qty = ref)}
style={DefaultStyles.SeedFundSummaryTextInput}
keyboardType='numeric'
disabled={this.props.navigation.state.params.edit == false}
theme={{ colors: { text: 'rgba(0, 0, 0, .5)' } }}
// value={item.qty <= item.allowed_bags&&this.state.enable_pc_limit_check==1?
item.qty.toString() : ''}
value={ item.qty}
onBlur={ (text) => this.handleOnBlur(text) }
maxLength={5}
onChangeText={(text) => { /*item.qty = text;*/ this.handleBags(text, item)}} />
async handleOnBlur(text){
console.log(text,'onBlur')
}
Here is my code, i want to get the text in Onblur function as i get in onchangetext. What should i do?
The event is passed as param to onBlur callback, which you can get text from via nativeEvent prop:
<TextInput onBlur={e => console.log('text', e.nativeEvent.text)}/>
You can find more info here

How to get my Autocomplete input field to reset DefaultValue after submit?

How can I get my <TextField> inside Autocomplete to reset it's default value after form submit?
Currently, the state of formValues during submit remains as the default value?
I've tried to fix the onSubmit function of my form to clear the state of the values, but not able to do so.
How can I clear the value after a user submits?
const { control, handleSubmit } = useForm();
const [formValues, SetFormValues] = useState()
const onSubmit = (data, e) =>
{
console.log(data);
axiosInstance
.patch(URL + slug + '/', {
stock_list: data.stock_list.map(list=>list.symbol),
})
.then((res) =>
{
getFinData(dispatch)(slug);
SetFormValues([''])
console.log(formValues)
});
};
console.log(formValues)
return (
<Container component="main" maxWidth="md">
<div className={classes.container}>
<Grid>
<form noValidate onSubmit = { handleSubmit(onSubmit) }>
<Controller
render={({ onChange ,...props }) => (
<Autocomplete
{...props}
className={classes.inputBar}
id="stock_list"
key={formValues}
name="stock_list"
multiple
options={options}
ListboxComponent={ListboxComponent}
renderGroup={renderGroup}
filterOptions={filterOptions}
filterSelectedOptions
// onChange={(e) => onChange(e.target.value)}
onChange={(e, data) => { onChange(data); SetFormValues(data) }}
getOptionLabel={(option) => option.symbol}
getOptionSelected={(option, value) => option.symbol === value.symbol}
renderOption={(option) =>
{
return (
<>
<span style={{ fontWeight: 500, fontSize: "20px", paddingRight: "1rem" }}>{option.symbol}</span><span style={{ color: "#C6C6C6", fontSize: "24px" }}> | </span><span style={{ paddingLeft: "1rem" }}>{option.company}</span>
</>
)
}}
renderInput={(params) => (
<Zoom in={tabSwitch === 0}>
<TextField
{...params}
style={{ alignItems: 'center' }}
id="stock_list"
name="stock_list"
variant="outlined"
label="Companies"
className={classes.inputBar}
defaultValue={formValues}
/>
</Zoom>
)}
/>
)}
name="stock_list"
control={control}
defaultValue={formValues}
// onChange={([, data]) => data}
/>
{formValues && formValues.length > 0 &&
<Button
variant="contained"
color="primary"
type="submit"
style={{display:"flex",alignItems: 'center',justifyContent:"center"}}
>
Add Stocks
</Button>
}
</form>
</Grid>
</div>
</Container>
);
})
UPDATE:
I have tried implementing your codes but still no success in removing the data from original state?
const [formValues, SetFormValues] = useState([])
const onSubmit = (data, e) =>
{
console.log(data);
axiosInstance
.patch(URL + slug + '/', {
stock_list: data.stock_list.map(list=>list.symbol),
})
.then((res) =>
{
getFinData(dispatch)(slug);
SetFormValues([]);
});
};
return (
<Controller
render={({ onChange ,...props }) => (
<Autocomplete
{...props}
className={classes.inputBar}
id="stock_list"
key={formValues}
name="stock_list"
multiple
options={options}
ListboxComponent={ListboxComponent}
renderGroup={renderGroup}
filterOptions={filterOptions}
filterSelectedOptions
onChange={(e, data) => { onChange(data); SetFormValues(data) }}
getOptionLabel={(option) => option.symbol}
getOptionSelected={(option, value) => option.symbol === value.symbol}
renderOption={(option) =>
{
return (
<>
<span style={{ fontWeight: 500, fontSize: "20px", paddingRight: "1rem" }}>{option.symbol}</span><span style={{ color: "#C6C6C6", fontSize: "24px" }}> | </span><span style={{ paddingLeft: "1rem" }}>{option.company}</span>
</>
)
}}
renderInput={(params) => (
<Zoom in={tabSwitch === 0}>
<TextField
{...params}
style={{ alignItems: 'center' }}
id="stock_list"
name="stock_list"
variant="outlined"
label="Companies"
className={classes.inputBar}
defaultValue={formValues}
value={formValues}
/>
</Zoom>
)}
/>
)}
name="stock_list"
control={control}
defaultValue={[]}
/>
It might be worth noting that my Mui AutoComplete and textfield is wrapped around by React Hook Form controller.
There is error in your code.
When using state, specify the data type to be stored.
E.g
if you are storing array of data, your state should be const [formValues, SetFormValues] = useState([]); not const [formValues, SetFormValues] = useState();
if you are storing string of data, your state should be const [formValues, SetFormValues] = useState(""); not const [formValues, SetFormValues] = useState();
if you are storing integer of data, your state should be const [formValues, SetFormValues] = useState(0); not const [formValues, SetFormValues] = useState();
To clear the state of each of these data
For Array
SetFormValues([]);
For String
SetFormValues("");
For Int
SetFormValues(0);
So correct your code and ty again. It will work for you.
put this code in the then callback of axios SetFormValues([]);
Because defaultValue is default value..
Try looks like this; (add value)
<TextField
style={{ alignItems: 'center' }}
id="stock_list"
name="stock_list"
variant="outlined"
label="Companies"
defaultValue={formValues}
value={formValues}
/>
https://material-ui.com/api/input/#main-content
defaultValue: The default input element value. Use when the component is not controlled.
value: The value of the input element, required for a controlled component.
You can do it this way
const [formValues, SetFormValues] = useState(null)
Put this code in the then callback of axios SetFormValues(null);
OR
const [formValues, SetFormValues] = useState([])
Put this code in the then callback of axios SetFormValues(null);
If any of those two above does not work for you, try storing the values as string in state
E.g const [formValues, SetFormValues] = useState("")
and clear items using SetFormValues(null) or SetFormValues("");

Updating data on an index of a array javascript and react native

In my Todo App i have sucessfully implemented the add and delete functions but the update function is having trouble. What i need it to do is when i click the touchable opacity of a Todo, it should appear in my inputbox and if any change is made then that todo should be updated e.g clicking on abcd must make it appear in input box and changes made to it should be updated. Picture is also added below
export default function Todo() {
const [getText, setText] = useState('');
const [getList, setList] = useState([]);
const addItem = () => {
setList([...getList, {key: Math.random().toString(), data: getText}]);
setText('');
}
const removeItem = (itemKey) => {
setList(() => getList.filter(item => item.key != itemKey));
}
const updateFieldChanged = (index) => e => {
let newArr = [...getList]; // copying the old datas array
newArr[index] = e.target.value; // replace e.target.value with whatever you want to change it to
setList(newArr);
}
return (
<View style={styles.container}>
<Text style={styles.title}>todo</Text>
<View style={styles.inputContainer}>
<TextInput
style={styles.textInput}
placeholder="Enter Item"
onChangeText={text => setText(text)}
value={getText}
/>
<CustomButton
text = 'add'
color='red'
title= 'add'
textSize={20}
textColor="white"
onPressEvent={addItem}
/>
</View>
<ScrollView style={styles.scrollview}>
{getList.map((item, id) =>
<TouchableOpacity
key={item.key}
activeOpacity={0.7}
onPress= {() => updateFieldChanged(id)}
>
<View style={styles.scrollviewItem}>
<Text style={styles.scrollviewText}>{id}) {item.data}</Text>
<TouchableOpacity
onPress={() => removeItem(item.key)}
>
<View style={styles.crosstextcontainer}>
<Text style={styles.crosstext}>X</Text>
</View>
</TouchableOpacity>
</View>
</TouchableOpacity>
)}
</ScrollView>
</View>
);
}
Change
<TouchableOpacity
key={item.key}
activeOpacity={0.7}
onPress= {() => updateFieldChanged(id)}
>
to
<TouchableOpacity
key={item.key}
activeOpacity={0.7}
onPress= {() => updateFieldChanged(id,getText)}
>
Here iam passing the text that you need to enter to update a particular field
change your updateFieldChanged like this:
const updateFieldChanged = (index, text) => {
let newArr = [...getList]; // copying the old datas array
newArr[index].data = text; // replace e.target.value with whatever you want to change it to
setList(newArr);
setText('');
}
Here iam assigning the text you entered in the TextInput to the data object, which will update the array.
Hope this helps!

How to autofocus next TextInput on react-native

I'm trying to create a passcode protected screen. The screen will uses 4 numeric input as the passcode.
The way I'm doing this is create a TextInput Component and call it 4 times in my main screen.
The problem I'm having is the TextInputs will not focus on the next one as I type the value of the previous TextInput.
I'm using refs for all PasscodeTextInput component (I've been informed that it is a legacy method but I do not know any other way, alas).
Tried this method(without creating my own component), no luck too.
METHOD
index.ios.js
import React, { Component } from 'react';
import { AppRegistry, TextInput, View, Text } from 'react-native';
import { PasscodeTextInput } from './common';
export default class ProgressBar extends Component {
render() {
const { centerEverything, container, passcodeContainer, textInputStyle} = styles;
return (
<View style={[centerEverything, container]}>
<View style={[passcodeContainer]}>
<PasscodeTextInput
autoFocus={true}
ref="passcode1"
onSubmitEditing={(event) => { this.refs.passcode2.focus() }} />
<PasscodeTextInput
ref="passcode2"
onSubmitEditing={(event) => { this.refs.passcode3.focus() }} />
<PasscodeTextInput
ref="passcode3"
onSubmitEditing={(event) => { this.refs.passcode4.focus() }}/>
<PasscodeTextInput
ref="passcode4" />
</View>
</View>
);
}
}
const styles = {
centerEverything: {
justifyContent: 'center',
alignItems: 'center',
},
container: {
flex: 1,
backgroundColor: '#E7DDD3',
},
passcodeContainer: {
flexDirection: 'row',
},
}
AppRegistry.registerComponent('ProgressBar', () => ProgressBar);
PasscodeTextInput.js
import React from 'react';
import {
View,
Text,
TextInput,
Dimensions
} from 'react-native';
const deviceWidth = require('Dimensions').get('window').width;
const deviceHeight = require('Dimensions').get('window').height;
const PasscodeTextInput = ({ ref, autoFocus, onSubmitEditing, onChangeText, value}) => {
const { inputStyle, underlineStyle } = styles;
return(
<View>
<TextInput
ref={ref}
autoFocus={autoFocus}
onSubmitEditing={onSubmitEditing}
style={[inputStyle]}
maxLength={1}
keyboardType="numeric"
placeholderTextColor="#212121"
secureTextEntry={true}
onChangeText={onChangeText}
value={value}
/>
<View style={underlineStyle} />
</View>
);
}
const styles = {
inputStyle: {
height: 80,
width: 60,
fontSize: 50,
color: '#212121',
fontSize: 40,
padding: 18,
margin: 10,
marginBottom: 0
},
underlineStyle: {
width: 60,
height: 4,
backgroundColor: '#202020',
marginLeft: 10
}
}
export { PasscodeTextInput };
Update 1
index.ios.js
import React, { Component } from 'react';
import { AppRegistry, TextInput, View, Text } from 'react-native';
import { PasscodeTextInput } from './common';
export default class ProgressBar extends Component {
constructor() {
super()
this.state = {
autoFocus1: true,
autoFocus2: false,
autoFocus3: false,
autoFocus4: false,
}
}
onTextChanged(t) { //callback for immediate state change
if (t == 2) { this.setState({ autoFocus1: false, autoFocus2: true }, () => { console.log(this.state) }) }
if (t == 3) { this.setState({ autoFocus2: false, autoFocus3: true }, () => { console.log(this.state) }) }
if (t == 4) { this.setState({ autoFocus3: false, autoFocus4: true }, () => { console.log(this.state) }) }
}
render() {
const { centerEverything, container, passcodeContainer, testShit, textInputStyle } = styles;
return (
<View style={[centerEverything, container]}>
<View style={[passcodeContainer]}>
<PasscodeTextInput
autoFocus={this.state.autoFocus1}
onChangeText={() => this.onTextChanged(2)} />
<PasscodeTextInput
autoFocus={this.state.autoFocus2}
onChangeText={() => this.onTextChanged(3)} />
<PasscodeTextInput
autoFocus={this.state.autoFocus3}
onChangeText={() => this.onTextChanged(4)} />
<PasscodeTextInput
autoFocus={this.state.autoFocus4} />
</View>
</View>
);
}
}
const styles = {
centerEverything: {
justifyContent: 'center',
alignItems: 'center',
},
container: {
flex: 1,
backgroundColor: '#E7DDD3',
},
passcodeContainer: {
flexDirection: 'row',
},
}
AppRegistry.registerComponent('ProgressBar', () => ProgressBar);
There is a defaultProp for TextInput where one can focus after component mounted.
autoFocus
If true, focuses the input on componentDidMount, the default value is false. for more information please read the related Docs.
UPDATE
After componentDidUpdate it won't work properly. In that case, one can use ref to focus programmatically.
You cannot forward the ref to <TextInput> using that way because ref is one of the special props. Thus, calling this.refs.passcode2 will return you <PasscodeTextInput> instead.
Try change to the following to get the ref from <TextInput>.
PasscodeTextInput.js
const PasscodeTextInput = ({ inputRef, ... }) => {
...
return (
<View>
<TextInput
ref={(r) => { inputRef && inputRef(r) }}
...
/>
</View>
...
);
}
Then, assign the inputRef from <PasscodeTextInput> to a variable and use focus() to switch focus (it is not deprecated as of RN 0.41.2).
index.ios.js
return (
<PasscodeTextInput
autoFocus={true}
onChangeText={(event) => { event && this.passcode2.focus() }} />
<PasscodeTextInput
inputRef={(r) => { this.passcode2 = r }}
onChangeText={(event) => { event && this.passcode3.focus() }} />
<PasscodeTextInput
inputRef={(r) => { this.passcode3 = r }}
onChangeText={(event) => { event && this.passcode4.focus() }} />
<PasscodeTextInput
inputRef={(r) => { this.passcode4 = r }} />
);
P.S: event && this.passcode2.focus() prevents focus is switched when trying to clear the old passcode and enter a new one.
we handled this style of screen with a different approach.
Rather than manage 4 individual TextInputs and handle the navigation of focus across each one (and then back again when the user deletes a character), we have a single TextInput on screen but is invisible (ie. 0px x 0px) wide which has the focus, maxLength and keyboard configuration, etc.
This TextInput takes input from the user but can't actually been seen, as each character is typed in we render the entered text as a series simple View/Text elements, styled much similar to your screen above.
This approach worked well for us with no need to manage what the 'next' or 'previous' TextInput to focus next to.
You can use focus method onChangeText as Jason stated, in addition to that adding maxLength={1} can make you jump to the next input immediately without checking what's added. (just noticed its deprecated, but still this is how I solved my problem, and should do fine until v0.36, and this link explains how you should update the deprecated function).
<TextInput
ref="first"
style={styles.inputMini}
maxLength={1}
keyboardType="numeric"
returnKeyType='next'
blurOnSubmit={false}
placeholderTextColor="gray"
onChangeText={(val) => {
this.refs['second'].focus()
}}
/>
<TextInput
ref="second"
style={styles.inputMini}
maxLength={1}
keyboardType="numeric"
returnKeyType='next'
blurOnSubmit={false}
placeholderTextColor="gray"
onChangeText={(val) => {
this.refs['third'].focus()
}}
/>
...
Please notice that my use of refs are deprecated too, but I've just copied the code since I can guarantee you that was working back then (hopefully works now too).
Finally, the main issue with this type of implementation is, once you try to remove a number with backspace your focus will jump to next one, causing serious UX issues. However, you can listen for backspace key entry and perform something different instead of focusing to next input. So I'll leave a link here for you to further investigate if you choose to use this type of implementation.
Hacky Solution to Previously Described Issue: If you check what's entered in onChangeText prop before doing anything, you can jump to next input if the value is a number, else (that's a backspace), jump back. (Just came up with this idea, I haven't tried it.)
I think the issue is that onSubmitEditing is when you hit the "return" or "enter" key on the regular keyboard... there is not one of those buttons on the keypad.
Assuming you want each input to only have one character, you could look at the onChangeText and then check if text has length 1 and call focus if the length is indeed 1.
<TextInput
ref={input => {
this.nameOrId = input;
}}
/>
<TouchableOpacity
onPress={()=>{
this.nameOrId.focus()
}}
>
<Text>Click</Text>
</TouchableOpacity>
I solve with this code:
const VerifyCode: React.FC = ({ pass, onFinish }) => {
const inputsRef = useRef<Input[] | null[]>([]);
const [active, setActive] = useState<number>(0);
const onKeyPress = ({ nativeEvent }:
NativeSyntheticEvent<TextInputKeyPressEventData>) => {
if (nativeEvent.key === "Backspace") {
if (active !== 0) {
inputsRef.current[active - 1]?.focus();
return setActive(active - 1);
}
} else {
inputsRef.current[active + 1]?.focus();
return setActive(active + 1);
}
return null;
};
return (
<View style={styles.container}>
<StyledInput
onKeyPress={onKeyPress}
autoFocus={active === 0}
ref={(r) => {
inputsRef.current[0] = r;
}}
/>
<StyledInput
onKeyPress={onKeyPress}
autoFocus={active === 1}
ref={(r) => {
inputsRef.current[1] = r;
}}
/>
<StyledInput
onKeyPress={onKeyPress}
autoFocus={active === 2}
ref={(r) => {
inputsRef.current[2] = r;
}}
/>
<StyledInput
onKeyPress={onKeyPress}
autoFocus={active === 3}
ref={(r) => {
inputsRef.current[3] = r;
}}
/>
</View>
);
};
export default VerifyCode;
I put one ref in all the inputs, and when the onKeyPress fire, the function verify if have to go back or go to next input
Solved it by removing autoFocus={true} and setting timeout.
I have a popup as a functional component and using "current.focus()" with Refs like this:
const Popup = ({ placeholder, autoFocus, showStatus, }) => { const inputRef = useRef(null); useEffect(() => {
Platform.OS === 'ios'
? inputRef.current.focus()
: setTimeout(() => inputRef.current.focus(), 40); }, [showStatus]); return (
<View style={styles.inputContainer}>
<TextInput
style={styles.inputText}
defaultValue={placeholder}
ref={inputRef}
/>
</View> };

Disable the input from react-native-autocomplete-input

I'm using react-native-autocomplete-input and I'd like disable the <Autocomplete /> input. I tried adding disabled={this.state.loading} (disabling it while the data loads...right now the user can start typing before the autocomplete is available).
I'm confident there's a way to do so but I haven't been able to figure it out. Code below:
<Autocomplete
data={data}
defaultValue={query}
listStyle={styles.autoCompleteItems}
onChangeText={(text) => this.setState({query: text})}
renderItem={(data) => (
<TouchableOpacity onPress={() =>
this.setState({query: data.name, schoolId: data.id, social: data.social})
}
>
<Text>{data.name}</Text>
</TouchableOpacity>
)}
/>
react-native-autocomplete-input itself does not provide functionality to disable the input field. So passing disabled={this.state.loading} will have no effect.
You can edit the the package by going into your node_modules/react-native-autocomplete-input folder and editing index.js file.
change the render function in index.js to following. Now its accepting isEditable prop and passing it to TextInput
render() {
const { showResults } = this.state;
const { containerStyle, inputContainerStyle, onEndEditing, isEditable, style, ...props } = this.props;
return (
<View style={[styles.container, containerStyle]}>
<View style={[styles.inputContainer, inputContainerStyle]}>
<TextInput
editable={isEditable}
style={[styles.input, style]}
ref="textInput"
onEndEditing={e =>
this._showResults(false) || (onEndEditing && onEndEditing(e))
}
{...props}
/>
</View>
{showResults && this._renderItems()}
</View>
);
}
Now you can pass isEditable={this.loading} as a prop to <Autocomplete />

Categories