I am trying to build a form in React Native using React Redux Form but I can use the <TextInput> for Email & Password but now I would like to use some checkboxes and dropdowns. Their documentationm doesn't provide an React Native guideline or any examples as they use simply <Input> tag for any inputs but how do i use this in React Native?
Here is my field render I use for email:
const renderField = ({ label, type, keyboardType, name, meta: { touched, error }, input: { onChange, ...restInput } }) => {
return (
<View style={{ flexDirection: 'column', height: 70, alignItems: 'flex-start' }}>
<View style={{ flexDirection: 'row', height: 30, alignItems: 'center', borderColor: 'black', borderBottomWidth: 1, }}>
<FontAwesome name='email-outline' size={18} color='#cccccc' style={{ paddingLeft: 2 }} />
<TextInput style={{ height: 37, width: 280, paddingLeft: 10, fontSize: 20 }}
keyboardType={keyboardType} onChangeText={onChange} {...restInput}
placeholder={label}
>
</TextInput>
</View>
{touched && ((error && <Text style={{ color: 'red', }}>{error}</Text>))}
</View>);
};
<Field keyboardType='email-address' type='email' label='Email' component={renderField} name='email' />
And what's the problem?
Just create a checkboxField component that you'll use instead of renderField in the places you need. And simply use the onChange function from the props to set a value and value as the value itself.
Here is an example that would be easier to understand:
const renderField = ({ input: { onChange, value } }) => {
return (
<View>
<Switch
onValueChange={(value) => onChange(value)}
value={value}
/>
</View>
);
};
Related
I have a FlatList using the ListHeaderComponent and ListFooterComponent.
Is there a way to style a container of the items (which come from the data prop), but not include the header and footer with in?
https://snack.expo.io/#jamesweblondon/bold-pretzel
import React from "react";
import { View, Text, FlatList } from "react-native";
const exampleData = [...Array(20)].map((d, index) => ({
key: `item-${index}`,
label: index,
backgroundColor: `rgb(${Math.floor(Math.random() * 255)}, ${
index * 5
}, ${132})`,
}));
const Example = () => {
const renderItem = ({ item }) => {
return (
<View
style={{
flexDirection: "row",
width: "100%",
backgroundColor: item.backgroundColor,
}}
>
<Text
style={{
fontWeight: "bold",
color: "white",
fontSize: 32,
height: 100,
}}
>
{item.label}
</Text>
</View>
);
};
return (
<View style={{ flex: 1 }}>
<FlatList
data={exampleData}
renderItem={renderItem}
keyExtractor={(item) => item.key}
ListHeaderComponent={
<View
style={{
backgroundColor: "grey",
height: 200,
justifyContent: "center",
alignItems: "center",
}}
>
<Text>Before list</Text>
</View>
}
ListFooterComponent={
<View
style={{
backgroundColor: "grey",
height: 200,
justifyContent: "center",
alignItems: "center",
}}
>
<Text>After list</Text>
</View>
}
/>
<View
style={{
backgroundColor: "gold",
height: 200,
justifyContent: "center",
alignItems: "center",
}}
>
<Text>Footer</Text>
</View>
</View>
);
};
export default Example;
Currently it looks like this:
Id like an element allowing me to wrap data so I can add padding, border, etc:
You can use columnWrapperStyle prop instead of contentContainerStyle prop of FlatList. This will help you to make styling of the wrapper of the components generated from the data.
For demo just add border property and you will see this will only apply styles to the container of items and not to ListHeaderComponent and ListFooterComponent
Example
<FlatList
....
columnWrapperStyle={{borderWidth: 1, borderColor: 'red'}}
/>
Note: Please make sure as the name of the prop suggests, the style will be applied to each colum. Also if this prop does not work for you then consider using numColumns prop of FlatList first then apply style with columnWrapperStyle
Check out the contentContainerStyle prop in FlatList, it should help you do exactly what you are looking for.
I have found a workaround that works for me, but I'm not sure if it can cause performance issues, so beware.
The idea is to have two FlatLists, where the one containing your actual list is the FooterListComponent of the other one.
N.B. notice how it's not a FlatList wrapped in a ScrollView, which would trigger the Virtualizedlists should never be nested inside plain scrollviews error.
Here's the code
const MyComponent = () => {
return (
<FlatList
data={[]}
renderItem={() => undefined}
ListHeaderComponent={ListHeader} // whatever you want above your list
ListFooterComponent={() => {
return (
<View style={yourContainerStyle}>
<FlatList
data={data}
renderItem={renderItem}
/>
</View>
);
}}
/>)
}
I’m setting up a new component,
and the keyboard covers the fields
This is for a new component
<KeyboardAwareScrollView enableOnAndroid={true} extraScrollHeight={50} enableAutomaticScroll={true}>
<View style={{ paddingHorizontal: 20 }}>
<View>
<FloatingLabelInput
onRef={(ref) => {
this.inputs['firstName'] = ref
}}
onSubmitEditing={() => {
this.focusNextField('lastName')
}}
label={i18n.t('t_driver_registration_first_name_label')}
onChangeText={(text) => this.onChangeInputText('firstName', text)}
keyboardType='default'
maxLength={20}
value={form.firstName}
labelStyle={Style.inputLabel}
basicColor={GStyle.GREEN}
inputTextColor={Color(GStyle.BLACK).alpha(.7)}
editable={mode !== DriverFormMode.EDIT}
/>
I expect the keyboard will not cover my fields.
Wrap your view in this to scroll automatically on input focus. Do:
<KeyboardAvoidingView style={{ flex: 1, flexDirection: 'column',justifyContent: 'center',}} behavior="padding" enabled keyboardVerticalOffset={100}>
<ScrollView>
<View style={Styles.row}>
//your view
</View>
</ScrollView>
</KeyboardAvoidingView>
<View style={Styles.row}> This is just a Stylesheet e.g. Create a new StyleSheet:
const Styles = StyleSheet.create({
row: {
borderRadius: 4,
borderWidth: 0.5,
borderColor: '#d6d7da',
},
title: {
fontSize: 19,
fontWeight: 'bold',
},
activeTitle: {
color: 'red',
},
});
Use a StyleSheet:
<View style={Styles.row}>
<Text style={[Styles.title, this.props.isActive && styles.activeTitle]} />
</View>
I have a modal with diffrent tabs in my app in which user can filter the search result with categories in the modal . right now it is working but I simply put an event on a <TEXT> , I need some visual clue like checkbox for my options
{this.state.currentTab === 1 && (
<View>
<Text onPress={(text) => this.setGender(true)}>male</Text>
<Text onPress={(text) => this.setGender(false)}>female</Text>
</View>
)}
How Can I use checkbox instead of <TEXT> to use both in android and IOS?
You can use this library for the checkbox
" react-native-circle-checkbox "
import CircleCheckBox, {LABEL_POSITION} from 'react-native-circle-checkbox';
{this.state.currentTab === 1 && (
<View>
<CircleCheckBox
checked={true}
onToggle={(text) => this.setGender(true)}
labelPosition={LABEL_POSITION.RIGHT}
label="MALE"
/>
<CircleCheckBox
checked={true}
onToggle={(text) => this.setGender(false)}
labelPosition={LABEL_POSITION.RIGHT}
label="FEMALE"
/>
</View>
)}
Example: https://snack.expo.io/#msbot01/intrigued-marshmallows
Use This Component which I manually created. It renders same radio button on both platforms
const RenderRadio = (props) => {
const {
value, onChange, selectedValue
} = props;
const checked = value === selectedValue;
return (
<TouchableOpacity
style={{ flexDirection: 'row' }}
onPress={() => onChange(value)}
>
<View
style={{
width: 20,
height: 20,
borderRadius: 10,
borderWidth: 2,
borderColor: '#002451',
justifyContent: 'center',
alignItems: 'center',
}}
>
<View
style={{
width: 10,
height: 10,
borderRadius: 5,
backgroundColor: checked ? '#002451' : 'white',
}}
/>
</View>
<Text style={{ fontSize: 15, marginLeft: 10 }}>{value}</Text>
</TouchableOpacity>
);
};
use it as
<RenderRadio onChange={this.setSelectedValue} selectedValue={selectedValue} value={value}/>
and set Your selected value as
setSelectedValue = (value) => {
this.setState(selectedValue : value)
}
You can use native-base library, that has more components which you can use for Search filters and this is more reliable, you can set it checked
using checked prop, that is boolean, like this :
import {
Icon,
CheckBox,
Spinner
} from "native-base";
<TouchableOpacity onPress={(text) => this.setGender(true)} >
<CheckBox checked ={tru}
onPress={(text) => this.setGender(true)} />
</TouchableOpacity>
I try to show how many character are left to input in my filed render but I get _this.setState is not a function. (in '_this.setState({value: value})','_this.setState' is undefined)
And here is my render
const renderField = ({ label, keyboardType, name, meta: { touched, error }, input: { onChange, ...restInput } }) => {
this.state = {
value: ''
}
return (
<View style={{ flexDirection: 'column', height: 70, alignItems: 'flex-start' }}>
<View style={{ flexDirection: 'row', alignItems: 'center', borderColor: 'black', borderBottomWidth: 1, }}>
<TextInput style={{ height: 37, width: 295, paddingLeft: 10, fontSize: 20, height: 350, justifyContent: "flex-start" }}
keyboardType={keyboardType} value={this.state.value} onChangeText={(value) => this.setState({ value })} {...restInput}
placeholder={label} numberOfLines={10} multiline={true} maxLength={100}
>
</TextInput>
</View>
<Text>
Characters Left: {this.state.value.length}/100
</Text>
{touched && ((error && <Text style={{ color: 'red', }}>{error}</Text>))}
</View>);
};
You have defined renderField as a functional component, a functional component is stateless by definition. In order to use state all you need to do is change this to class component.
Here is the official link to convert functional component to class component.
Hope this will help!
I am wondering if I can use autoGrow in redux form or I should use something else?
Here is my render code
const renderField = ({ label, keyboardType, name, meta: { touched, error }, input: {onChange, ...restInput} }) => {
return (
<View style={{flexDirection: 'column', height: 70, alignItems: 'flex-start'}}>
<View style={{flexDirection: 'row', height: 30, alignItems: 'center', borderColor: 'black', borderBottomWidth: 1,}}>
<TextInput style={{ height: 37, width: 280, paddingLeft: 10, fontSize: 20}}
keyboardType={keyboardType} onChangeText={onChange} {...restInput}
placeholder={label}
>
</TextInput>
</View>
{touched && ((error && <Text style={{color: 'red', }}>{error}</Text>))}
</View>);
};
You can use textArea to change the the number of rows and to expand the text area
const renderTextArea = ({ input, label, className, rows, meta: { touched, error, warning }}) => (
<div>
<div>
<textarea {...input} placeholder={label} rows={rows} cols="100" className={className}/>
{touched && ((error && <span className="error_field">{error}</span>) || (warning && <span>{warning}</span>))}
</div>
</div>
)