Created
April 22, 2019 19:51
-
-
Save omeileo/22054b4418f02491ee87ac0a4663d52c to your computer and use it in GitHub Desktop.
Navigate to next form field onSubmitEditing (React Native)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// External Dependencies | |
import React, { Component } from 'react' | |
import { View } from 'react-native' | |
import PropTypes from 'prop-types' | |
import _ from 'lodash' | |
// Internal Dependencies | |
import FormField from './FormField/FormField.component' | |
import styles from './Form.styles' | |
export default class Form extends Component { | |
constructor (props) { | |
super(props) | |
this.formField = {} | |
} | |
render () { | |
const { formFields } = this.props | |
this.refs = this.formField | |
return ( | |
<View style={styles.container}> | |
{ | |
formFields.map((formField, index) => { | |
const { | |
autoCapitalize, autoCorrect, blurOnSubmit, enablesReturnKeyAutomatically, | |
fieldName, isValid, maxLength, onBlur, onChangeText, onSubmitEditing, placeholder, | |
returnKeyType, secureTextEntry, text, textContentType, validation | |
} = formField | |
const nextFormFieldName = (index + 1 < formFields.length) ? formFields[index + 1].fieldName : null | |
const _onSubmitEditing = () => { | |
_.isNull(nextFormFieldName) | |
? onSubmitEditing() | |
: this.refs[nextFormFieldName].textInput[nextFormFieldName].focus() // textInput object is defined in FormField | |
} | |
return ( | |
<View style={styles.formFieldContainer} key={index}> | |
<FormField | |
autoCapitalize={autoCapitalize} | |
autoCorrect={autoCorrect} | |
blurOnSubmit={blurOnSubmit} | |
enablesReturnKeyAutomatically={enablesReturnKeyAutomatically} | |
fieldName={fieldName} | |
isValid={isValid} | |
maxLength={maxLength} | |
onBlur={onBlur} | |
onChangeText={onChangeText} | |
onSubmitEditing={_onSubmitEditing} | |
placeholder={placeholder} | |
returnKeyType={returnKeyType} | |
ref={ref => (this.formField[fieldName] = ref)} | |
secureTextEntry={secureTextEntry} | |
text={text} | |
textContentType={textContentType} | |
validation={validation} | |
/> | |
</View> | |
) | |
}) | |
} | |
</View> | |
) | |
} | |
} | |
Form.propTypes = { | |
formData: PropTypes.arrayOf(PropTypes.shape({ | |
autoCapitalize: PropTypes.string, | |
autoCorrect: PropTypes.bool, | |
blurOnSubmit: PropTypes.bool, | |
enablesReturnKeyAutomatically: PropTypes.bool, | |
fieldName: PropTypes.string.isRequired, | |
isValid: PropTypes.bool, | |
maxLength: PropTypes.number, | |
onBlur: PropTypes.func, | |
onChangeText: PropTypes.func, | |
onSubmitEditing: PropTypes.func, | |
placeholder: PropTypes.string, | |
returnKeyType: PropTypes.string, | |
secureTextEntry: PropTypes.bool, | |
text: PropTypes.string.isRequired, | |
textContentType: PropTypes.string, | |
validation: PropTypes.bool | |
}).isRequired) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// External Dependencies | |
import React, { Component } from 'react' | |
import { Image, Text, TextInput, TouchableOpacity, View } from 'react-native' | |
import PropTypes from 'prop-types' | |
import _ from 'lodash' | |
// Internal Dependencies | |
import colors from '../../../styles/colors' | |
import images from '../../../../assets/images/images' | |
import styles from './FormField.styles' | |
import { formFieldName } from '../../../dictionary' | |
export default class FormField extends Component { | |
constructor (props) { | |
super(props) | |
this.textInput = {} | |
} | |
state = { | |
isPasswordVisible: false | |
} | |
getErrorText = fieldName => { | |
const errorMessage = { | |
invalidPassword: 'Must Have At Least 8 Characters, 1 Number, & 1 Uppercase Letter.', | |
invalidName: `Not a Valid Name. Enter First and Last Name.`, | |
emailDuplicate: 'Email Already Exists', | |
invalidEmail: 'Not a Valid Email' | |
} | |
let text = '' | |
switch (fieldName) { | |
case formFieldName.email: | |
text = errorMessage.invalidEmail | |
break | |
case formFieldName.name: | |
text = errorMessage.invalidName | |
break | |
case formFieldName.password: | |
text = errorMessage.invalidPassword | |
break | |
} | |
return text | |
} | |
render () { | |
const { | |
autoCapitalize, autoCorrect, blurOnSubmit, enablesReturnKeyAutomatically, | |
fieldName, isValid, maxLength, onBlur, onChangeText, onSubmitEditing, | |
placeholder, returnKeyType, secureTextEntry, text, textContentType, validation | |
} = this.props | |
return ( | |
<View> | |
<View style={[styles.container, secureTextEntry && { paddingRight: 35 }]}> | |
<TextInput | |
autoCapitalize={autoCapitalize} | |
autoCorrect={autoCorrect} | |
blurOnSubmit={blurOnSubmit} | |
enablesReturnKeyAutomatically={enablesReturnKeyAutomatically} | |
maxLength={maxLength} | |
onBlur={onBlur} | |
onChangeText={text => onChangeText(text)} | |
onSubmitEditing={onSubmitEditing} | |
placeholder={placeholder} | |
ref={ref => (this.textInput[fieldName] = ref)} | |
placeholderTextColor={colors.grey.D8D8D8} | |
returnKeyType={returnKeyType} | |
secureTextEntry={this.state.isPasswordVisible ? false : secureTextEntry} | |
style={styles.formField} | |
textContentType={textContentType} | |
underlineColorAndroid={colors.transparent} | |
value={text} | |
/> | |
<View style={styles.formFieldIcons}> | |
{ | |
secureTextEntry && | |
<TouchableOpacity | |
hitSlop={{ left: 10, right: 10, top: 10, bottom: 10 }} | |
activeOpacity={0.8} | |
onPress={() => this.setState({ isPasswordVisible: !this.state.isPasswordVisible })} | |
> | |
<Image | |
source={this.state.isPasswordVisible ? images.passwordShown : images.passwordHidden} | |
style={styles.passwordVisibilityIcon} | |
/> | |
</TouchableOpacity> | |
} | |
{ | |
validation && | |
<View | |
style={[ | |
styles.validation, | |
!_.isNull(isValid) && | |
{ backgroundColor: isValid ? colors.green : colors.red } | |
]} | |
/> | |
} | |
</View> | |
</View> | |
{ | |
!_.isNull(isValid) && !isValid && validation && | |
<Text style={styles.errorText}>{this.getErrorText(fieldName)}</Text> | |
} | |
</View> | |
) | |
} | |
} | |
FormField.propTypes = { | |
autoCapitalize: PropTypes.string, | |
autoCorrect: PropTypes.bool, | |
blurOnSubmit: PropTypes.bool, | |
enablesReturnKeyAutomatically: PropTypes.bool, | |
fieldName: PropTypes.string.isRequired, | |
isValid: PropTypes.bool, | |
maxLength: PropTypes.number, | |
onBlur: PropTypes.func, | |
onChangeText: PropTypes.func, | |
onSubmitEditing: PropTypes.func, | |
placeholder: PropTypes.string, | |
returnKeyType: PropTypes.string, | |
secureTextEntry: PropTypes.bool, | |
text: PropTypes.string.isRequired, | |
textContentType: PropTypes.string, | |
validation: PropTypes.bool | |
} | |
FormField.defaultProps = { | |
validation: false, | |
onBlur: () => {}, | |
onChangeText: () => {}, | |
placeholder: '', | |
text: '' | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This gist shows how to dynamically navigate to the next form field in a react native form using just the inbuilt TextInput [wrapped in a View].
The takeaway is to give the FormField component itself a dynamically-generated unique ref (I used the name of the form field):
ref={ref => (this.textInput[fieldName] = ref)}
On the Form, you then want to give each FormField in the Form a ref:
ref={ref => (this.formField[fieldName] = ref)}
You then want to assign the object you stored your generated refs to the Form refs:
this.refs = this.formField
After which, you want to ascertain the next form field in the list of form fields (I passed mine as a list of objects):
const nextFormFieldName = (index + 1 < formFields.length) ? formFields[index + 1].fieldName : null
At which point you then determine if you need to go to the next field onSubmitEditing or Submit the form itself:
Finally, pass the custom _onSubmitEditing function to the TextInput:
onSubmitEditing={_onSubmitEditing}