How to pass value to placeholder to textInput in redux-form? - javascript

So I'm creating a login form with two fields, username & password respectively; and I would like to pass placeholder to each of these Field. however, no matter what I try, the placeholder is not shown.
Code
const submit = values => {
console.log('submitting form', values)
};
const renderInput = ({ input: { onChange, ...restInput } }) => {
return <TextInput style = { styles.input } onChangeText = { onChange } { ...restInput }/>
};
const LoginForm = props => { const { handleSubmit } = props;
return (
<View style={styles.container}>
<View>
<Field name="email" placeholder="Email" component={renderInput} />
<Field name="password" placeholder="Password" component={renderInput} />
</View>
<View>
<View style={styles.loginBtnContainer}>
<TouchableOpacity style={styles.button} onPress={handleSubmit(submit)}>
<Text style={{fontSize: 30, color: '#17a2e0'}}>Login</Text>
</TouchableOpacity>
</View>
</View>
</View>
)
}
export default reduxForm({
form: 'test'
})(LoginForm)
As you can see, the two fields with name email & password respectively are not present in TextInput in renderInput function.

In your component renderInput in its props you will have available the ones applied to the component Field. As documentation states, you just have to apply the attribute placeholder in the TextInput component to get placeholder rendered.
const renderInput = ({ placeholder, input: { onChange, ...restInput } }) => {
return <TextInput placeholder={placeholder} style = { styles.input } onChangeText = { onChange } { ...restInput }/>
};

Related

Why 'react-hook-form' gives empty data?

I am working in react-native and used 'react-hook-forms' for dynamic form creation,
but it's returning empty data object, but it should return values typed in input fields. onSubmit function gives an empty values. Please check my below code. please help me...
//InputBox.js. this my dynamic element where I want access its values in AddDirectries.js
import { useForm, Controller } from 'react-hook-form'
const InputBox = ({ fields, fieldName }) => {
let { control } = useForm();
return (
<>
{ fields.field_unit == null ? <Text style={styles.formsTitle}>{fieldName}</Text> :
<Text style={styles.formsTitle}> {fieldName + "(" + fields.field_unit + ")"}</Text>
}
{[...Array(fields.field_count)].map((item, index) => {
return (
<Controller
control={control}
name={'j' + index}
defaultValue=""
render={({ field: { onChange, onBlur, value } }) => (
<TextInput
onChangeText={value => onChange(value)}
value={value}
></TextInput>
)}
/>
)
})
})
</>)
}
export default InputBox;
//AddDirectries.js here I want access TextInput values.
import { useForm } from 'react-hook-form'
import Element from '../components/Element'
import FormJson from '../../From.json'
export const AddDirectories = (props) => {
let { handleSubmit, control, formState: { errors } } = useForm();
const [elements, setElements] = useState([]);
const [keys, setKeys] = useState([]);
const onSubmit = data => console.log(data);
useEffect(() => {
setKeys(Object.keys(FormJson))
setElements(FormJson)
}, [])
return (
<View style={[styles.mainScreen, { backgroundColor: 'transparent' }]}>
{
keys.map((fieldName, index) => {
return <Element fieldName={fieldName} fields={elements[keys[index]]} key={index}></Element>
})
}
<TouchableOpacity onPress={handleSubmit(onSubmit)} style={[styles1.addButton, { marginBottom: 30 }]}>
<Text>ADD</Text>
</TouchableOpacity>
</View>
)
}
//Element.js
const Element = ({fieldName, fields }) => {
switch (fields.field_type) {
case ("TextField"):
return (<InputLocation fields ={fields} fieldName={fieldName} />)
default: return null;
}
}
export default Element;
I just had the same problem.
instead of :
<Controller
control={control}
name={'j' + index}
defaultValue=""
render={({ field: { onChange, onBlur, value } }) => (
<TextInput
onChangeText={value => onChange(value)}
value={value}
></TextInput>
)}
/>
spread field into textinput:
<Controller
control={control}
name={'j' + index}
defaultValue=""
render={({ field }) => (
<TextInput
{...field}
onChangeText={value => field.onChange(value)}
value={field.value}
></TextInput>
)}
/>

Calling an Input in onPress

I am trying to call my emailInput and have it show up on my createPassword page, specifically where youremail#email.com is. I have given the two pages below, the email page consisting of a user input and the password page where I want that user input to appear on. I cannot really wrap my head around how to refer to the Input in my onPress. Any insight at all is appreciated more than you know!
Also, can I call two onPress's like that? Or do I need to create two functions and do it that way?
SignUpEmail.js
export default class SignUpEmailPage extends Component {
constructor() {
super();
this.state = {
color1: '#A2A2A2'};}
render() {
return (
<View style={styles.containerMain}>
{/* Email Input */}
<Container style = {styles.emailInput}>
<Form>
<Item floatingLabel >
<Label style={{color:this.state.color1}}>Email Address</Label>
<Input
style={styles.textInput}
autoCorrect={false}
autoCapitalize="none"
onFocus={() => this.setState({color1: '#F7018D'})}
onBlur={() => this.setState({color1: '#A2A2A2'})}
/>
</Item>
</Form>
</Container>
<View style={styles.containerBottom}>
<ContinueButton
onPress = {() => navigation.navigate('CreatePassword', { emailInput: })}
onPress={() => this.props.navigation.navigate('CreatePassword')}
/>
</View>
CreatePassword.js
export default class CreatePasswordPage extends Component {
constructor() {
super();
this.state = {
color1: '#A2A2A2'};}
render() {
return (
<View style={styles.containerMain}>
{/* Password Input */}
<Container style = {styles.passwordInput}>
<Form>
<Item floatingLabel>
<Label style={{color:this.state.color1}}>Password</Label>
<Input
style={styles.textInput}
autoCorrect={false}
autoCapitalize="none"
secureTextEntry={true}
onFocus={() => this.setState({color1: '#F7018D'})}
onBlur={() => this.setState({color1: '#A2A2A2'})}
/>
</Item>
</Form>
</Container>
<View style={styles.containerHeader}>
<Text style={styles.title}>Create a Password</Text>
</View>
<View style={styles.containerCaption}>
<Text style={styles.caption}> Lets create your Password for
</Text>
</View>
<View style={styles.containerCaption2}>
<Text style={styles.caption}> youremail#email.com</Text>
</View>
<View style= {styles.backArrowPlacement}>
<BackArrow
onPress={() => this.props.navigation.navigate('SignUpEmail')}
/>
</View>
<View style={styles.containerBottom}>
<ContinueButton
onPress={() => this.props.navigation.navigate('PhoneVerification')}
/>
</View>
</View>
);
}
}
You can't use navigation.navigate as it needs Hooks implementation in the functional component. You can do is
export default class SignUpEmailPage extends Component {
constructor() {
super();
this.state = {
color1: '#A2A2A2',
inputValue: '', // add state here
};
}
updateInputValue = (evt) => {
this.setState({
inputValue: evt.target.value
});
}
render() {
return (
<Input
value = {this.state.inputValue}
onChange={this.updateInputValue }
/>
<ContinueButton
//onPress = {() => navigation.navigate('CreatePassword', { emailInput: })} // remove this
onPress={() => this.props.navigation.navigate('CreatePassword',{ emailInput: this.state.inputValue })} // use this like
/>
)
}
}

how to acces to my checkbox component state?

Hi I am doing some kind of form in react native and i have this checkbox component that works fine, but i cant get his value on my form.js. I have the same problem with other components like datepicker. im unable to pass the values
any suggestion would be aprreciated
this is my checkbox component
import { CheckBox } from 'react-native-elements';
export default class CheckBoxs extends Component {
constructor() {
super();
this.state = {
checked1: true,
checked2: false,
};
}
render() {
return (
<View style={styles.checkbox} >
<CheckBox
containerStyle={styles.checkbox}
textStyle={styles.checkboxTxt}
uncheckedColor={'#b3b4b5'}
checkedColor={"#911830"}
key={1}
title="Mujer"
value={1}
value="1"
checkedIcon="stop"
checked={this.state.checked1}
onPress={() => this.setState({ checked1: !this.state.checked1, checked2: this.state.checked1 })}
/>
<CheckBox
containerStyle={styles.checkbox}
textStyle={styles.checkboxTxt}
uncheckedColor={'#b3b4b5'}
checkedColor={"#911830"}
key={0}
title="Hombre"
value={0}
value="0"
checkedIcon="stop"
checked={this.state.checked2}
onPress={() => this.setState({ checked2: !this.state.checked2, checked1: this.state.checked2 })}
/>
</View>
);
}
}
this is my form code
import CheckBoxs from './CheckBoxs';
const PersonalForm = ({onSubmit, errorMessage}) => {
import CheckBoxs from './CheckBoxs';
const PersonalForm = ({onSubmit, errorMessage}) => {
const [vName, setvName] = useState('');
const [vSecondName, setvSecondName] = useState('');
const [vLastName, setvLastName] = useState('');
const [vSecondLastName, setvSecondLastName] = useState('');
const [vCellphone, setvCellphone] = useState('');
const [vBirthDate, setvBirthDate] = useState('');
const [vRFC, setvRFC] = useState('');
const [vGender, setvGender] = useState('');
const [vEmail, setvEmail] = useState('');
const [checked] = useState('false');
return (
<ScrollView>
<View style={styles.buttonContainer}>
<View style={styles.inputContainer}>
<TextInput style={styles.inputs}
placeholder="Apellido materno"
onChangeText={newvSecondLastName => setvSecondLastName(newvSecondLastName)}
underlineColorAndroid='transparent'
value={vSecondLastName}
autoCorrect={false}
autoCapitalize='characters'
/>
</View>
<View>
<MyDatePicker />
</View>
<View style={styles.checkbox} >
<CheckBoxs />
</View>
<View style={styles.inputContainer}>
<TextInput style={styles.inputs}
placeholder="Correo electrónico"
underlineColorAndroid='transparent'
onChangeText={newvEmail => setvEmail(newvEmail)}
value={vEmail}
autoCorrect={false}
autoCapitalize='characters'
/>
</View>
</View>
<View style={styles.buttonContainer2}>
<TouchableOpacity
style={ styles.logout}
onPress={() => onSubmit(vName, vSecondName, vLastName, vSecondLastName, vCellphone, vBirthDate, vRFC, vGender, vEmail),console.log(vName, vSecondName, vLastName, vSecondLastName, vCellphone, vBirthDate, vRFC, vGender, vEmail)}
>
<Text style={styles.loginText}>GUARDAR</Text>
</TouchableOpacity>
</View>
</ScrollView>
);
};
Have your component accept an 'onChange' callback (via props), and invoke it with the new value, whenever the value changes.
For example:
<Parent>
<Kid onChange={ newValue => { /* use the new value... */ } }/>
</Parent
Or another example:
const Parent = () => (
<View>
<TwoCheckboxes
onChange={
newValues => console.log('parent got new values', newValues)
}
/>
</View>
);
const TwoCheckboxes = props => {
const [ values, setValues ] = useState([ true, false]);
const [ val1, val2 ] = values;
const updateValuesAndReportChange = (newValues) => {
setValues(newValues);
props.onChange(newValues); /** this will pass updated values to Parent */
};
return (
<View>
<Checkbox
onPress={ () => updateValuesAndReportChange([ !val1, val2 ]) }
/>
<Checkbox
onPress={ () => updateValuesAndReportChange([ val1, !val2 ]) }
/>
</View>
);
};
In the React Native Docs:
This is a controlled component that requires an onValueChange callback that updates the value prop in order for the component to reflect user actions. If the value prop is not updated, the component will continue to render the supplied value prop instead of the expected result of any user actions.
So, add onValueChange to your Checkbox component. Store the value that it gives you in the component state, and pass that state to Checkbox through its value property.
An Example:
<Checkbox onValueChange={value => /** update **/} value={/** stored value **/} ... />

How do I read an already populated TextInput in React-Native?

I have a TextInput below :
Normally I am able to read TextInput when there is a change , the problem is the TextInput for password is populated with a default password .
So the user may not need to edit(change) it - therefore not triggering onChangeText method .
import React,{Component} from 'react'
import {View, Text, TextInput } from 'react-native'
export default class App extends Component {
constructor(props){
super(props);
this.state = {
username: '',
password: 12345
}
}
onChangeText = (key, val) => {
this.setState({ [key]: val})
}
render() {
return (
<View style={styles.container}>
<Text>Login Form</Text>
<TextInput
placeholder='Username'
onChangeText={val => this.onChangeText('username', val)}
style={styles.input}
value={this.state.username}
/>
<TextInput
placeholder='Password'
onChangeText={val => this.onChangeText('password', val)}
style={styles.input}
value={this.state.password}
secureTextEntry={true}
/>
</View>
);
}
}
Now , my question is how do I read TextInputs which are not being changed ?
change TextInput value prop to defaultValue. i think that might work. TextInput value prop does't allow to modify existing value.
<TextInput
placeholder='Password'
onChangeText={val => this.onChangeText('password', val)}
style={styles.input}
defaultValue={this.state.password}
secureTextEntry={true}
/>
There is a way to get TextInput value directly from the component via refs.
If the input receives text from value prop you can use _lastNativeText method as in the example below.
export default class App extends Component {
state = {
text: 'Hello!'
}
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
componentDidMount() {
this.printTextInputValue();
}
printTextInputValue = () => {
const input = this.inputRef.current;
console.log(input._lastNativeText);
}
render() {
return (
<View style={styles.container}>
<TextInput value={this.state.text} ref={this.inputRef} />
<Button onPress={this.printTextInputValue} title="Get input value" />
</View>
);
}
}
If the TextInput uses defaultValue prop use _getText method to read the initial value.
export default class App extends Component {
constructor(props) {
super(props);
this.inputRef = React.createRef();
}
componentDidMount() {
this.printDefaultInputValue();
}
printDefaultInputValue = () => {
const input = this.inputRef.current;
console.log(input._getText());
}
printTextInputValue = () => {
const input = this.inputRef.current;
console.log(input._lastNativeText);
}
render() {
return (
<View style={styles.container}>
<TextInput defaultValue="Hello Default!" ref={this.inputRef} />
<Button onPress={this.printTextInputValue} title="Get input value" />
</View>
);
}
}
Do note however that these methods are not officially documented and may be removed in future versions of React Native, so use them at your own discretion.

save selected value to form field

I have a form where there is an input field for adding the user. It is a different kind of field. When user click on that field, the user is routed to another page where there is already a list of users and there a user can search as well. From that page, if user selects the particular user, he/she is redirected back to that form page and fill that field with the selected user name.
For now I have tried it as following
<Row>
<InputFieldWrapper label="Assigned to">
<Field
name="assigned_to"
input=""
placeholder="Search for contacts to assign"
readonly={false}
component={InputTextWithSearchField}
onPress={() => Actions[routeConstants.SEARCH_ASSIGNEE]({
keys : 'user',
data : taskValues ? taskValues.assigned_to : [],
faFetched: faFetched.users,
fieldName: 'assigned_to',
label : 'Assignee',
})}
/>
</InputFieldWrapper>
</Row>
const InputTextWithSearchField = props => {
let value = props.input.value || {};
makeUpdate = text => {
props.update(text);
};
return (
<View style={styles.inputFieldWrapper}>
<View style={styles.field}>
<TextInput
style={styles.inputField}
onChangeText={makeUpdate}
value={value.label}
placeholder={props.placeholder} />
</View>
<View style={styles.rightSideContent}>
<Icon
name="search"
size={26}
onPress={() => props.onPress()}
style={styles.searchField} />
</View>
</View>
);
};
class Search extends React.Component { // eslint-disable-line
state = {
items: [],
}
componentDidMount() {
this.update(' ');
}
// handleChange = data => {
// console.log('change', data);
// };
update = text => {
this.props.faFetched.sync(
{ search: text, priority_fields: 'personal.first_name,personal.last_name' }
).
then(res => this.setState({ items: res })).
catch(err => console.log(err)); // eslint-disable-line
};
itemSection = item => {
if(item)return alphabetic.map(alpha => {
return ({
title: alpha,
data : (item || []).filter(contact => contact.personal.first_name[0] === alpha)
});
});
};
renderHeader = ({ section }) => {
return <View style={styles.sectionHeader}>
<Text style={styles.sectionText}>
{section.title}
</Text>
</View>;
};
render() {
const { faFetched, data } = this.props;
const { items } = this.state;
return (
<View style={styles.container}>
<ActionButtons
label={this.props.label}
/>
<KeyboardAvoidingView keyboardVerticalOffset={0} behavior='padding'>
<ScrollView
keyboardShouldPersistTaps="always"
>
<View style={styles.formContainer}>
<Row zIndex={5}>
<InputFieldWrapper>
<Field
input=""
name={this.props.fieldName}
placeholder="Search contact"
update={this.update}
readonly={false}
component={InputTextWithSearchField}
/>
</InputFieldWrapper>
</Row>
</View>
<SectionList
sections={this.itemSection(items && items)}
renderItem={({ item, section }) => {
if(item)return <ListItem
item={item}
section={section} />;
}}
renderSectionHeader={items && this.renderHeader}
keyExtractor={item => item._id}
/>
</ScrollView>
</KeyboardAvoidingView>
</View>
);
}
}
class ListItem extends React.Component {
render() {
return (
<View style={styles.sectionItemWrapper}>
<TouchableOpacity onPress={() => null;}>
<Text style={styles.sectionItem}>
{this.props.item.personal.full_name}
</Text>
</TouchableOpacity>
</View>
);
}
}
It should be following
when user clicks on this input field, he/she will move to next step
next step is this and when user selects the name of user from the list he/she will be redirected back to the form page where that username should be filled in that field
Can anyone give me an idea, please? Right now I could only redirect the user to the contact list but I have no idea how can i route back to the same form page after user touches the contact list and fill the field with that value
If you are using react-navigation you can navigate back to the form page and send parameters along with.
this.props.navigation.navigate("form", {
userID:id,
userName: Name,
})
and then in componentdidmount method set value of text field to the one passed in parameters.
If you are using react-native-router-flux use
Actions.YOURSCENE({userID:id, userName: Name});
or use
Actions.pop({refresh: {userID:id, userName: Name}});
you may find the passed data in this.props

Categories