Show button when 2 inputs are full and valid in react native - reactjs

****I have a react native page app with 2 inputs. ****
I want to show the "submit" button once all of the 2 fields have a value.
(button is invisible until the 2 input fields have value)
this is my page code :
class Page3 extends Component {
render() {
const {navigate} = this.props.navigation;
return (
<View style={styles.container}>
<View style={styles.question1Stack}>
<Text style={styles.question1}>Question1</Text>
<ImageBackground
source={require("./assets/undraw_Friends_online_re_r7pq.png")}
resizeMode="contain"
style={styles.image}
imageStyle={styles.image_imageStyle}
>
<TouchableOpacity onPress={() =>{this.props.navigation.navigate('Page2')}}>
<Icon name="chevron-left" style={styles.icon1}></Icon>
</TouchableOpacity>
</ImageBackground>
</View>
<TouchableOpacity
title="submit"
onPress={() => {
this.props.navigation.navigate('Page4');
}}>
<Text style={styles.next}>
Next
</Text>
</TouchableOpacity>
<MaterialHelperTextBox
style={styles.materialHelperTextBox}
></MaterialHelperTextBox>
<MaterialHelperTextBox1
style={styles.materialHelperTextBox1}
></MaterialHelperTextBox1>
</View>
);
}
}
these are my input fields :
<MaterialHelperTextBox
style={styles.materialHelperTextBox}
></MaterialHelperTextBox>
<MaterialHelperTextBox1
style={styles.materialHelperTextBox1}
></MaterialHelperTextBox1>

you most define to two state for two TextInput , than set TextInput value in onChangeText check value is not null and valid , set true states for check, I don't know you use MaterialHelperTextBox1 by witch component but code maybe like this:
class Page3 extends Component {
constructor(props) {
super(props);
this.state = {
checkInput1:false,
checkInput2:false,
inputValue1:'',
inputValue2:'',
};
};
render() {
const {navigate} = this.props.navigation;
return (
<View style={styles.container}>
<View style={styles.question1Stack}>
<Text style={styles.question1}>Question1</Text>
<ImageBackground
source={require("./assets/undraw_Friends_online_re_r7pq.png")}
resizeMode="contain"
style={styles.image}
imageStyle={styles.image_imageStyle}
>
{checkInput1 && checkInput2 ?
<TouchableOpacity onPress={() =>
{this.props.navigation.navigate('Page2')}}>
<Icon name="chevron-left" style={styles.icon1}></Icon>
</TouchableOpacity>
:
null
}
</ImageBackground>
</View>
<TouchableOpacity
title="submit"
onPress={() => {
this.props.navigation.navigate('Page4');
}}>
<Text style={styles.next}>
Next
</Text>
</TouchableOpacity>
<MaterialHelperTextBox
style={styles.materialHelperTextBox}
onChangeText={value => {this.setstate({inputValue1:value});
_checkInputIsValid1();}}
defaultValue={this.state.inputValue1}
></MaterialHelperTextBox>
<MaterialHelperTextBox1
style={styles.materialHelperTextBox1}
onChangeText={value => {this.setstate({inputValue2:value});
_checkInputIsValid2();}}
defaultValue={this.state.inputValue1}
></MaterialHelperTextBox1>
</View>
);
}
}
_checkInputIsValid1(){
//check your rules for input1 there if true set state checkInput1 as true
}
_checkInputIsValid2(){
//check your rules for input2 there if true set state checkInput2 as true
}

Related

React Native class component accordion into functional component

The following code displays an accordion but I need to make use of useContext which I understand only works with functional components and I'm having a hard time understand how to convert it into a functional component.
class AnnualFeeScreen extends Component {
state = {
activeSections: [],
};
_renderHeader(section, index, isActive) {
let meanValStatus = '#39D0B5';
if (section.meanDiffVal >= 1.05) {
meanValStatus = '#FCD561';
} else if (section.meanDiffVal < 0.95) {
meanValStatus = '#bbb';
}
return (
<View style={styles.flexRow}>
<View style={{flex:2}}>
<Text style={styles.h6}>{!isActive ? '+' : '-'} {section.title}</Text>
</View>
<View style={styles.flex}>
<Text style={[styles.h6, {textAlign: 'right'}]}>{Math.round((section.titleValue) / 12, 0)} kr/mån</Text>
</View>
<View style={[styles.circleStatus, {backgroundColor: meanValStatus}]}></View>
</View>
);
};
_renderContent = section => {
return (
<View>
{section.content.map((item, key) =>
<View style={styles.accordionContent} key={key}>
<View style={styles.flexRow}>
<View style={{flex: 2}}>
<Text style={[styles.p, {fontWeight: 'normal'}]}>{item.title}</Text>
</View>
<View style={styles.flex}>
<Text style={[styles.p, {fontWeight: 'normal', textAlign: 'right'}]}>{Math.round((item.value * aptPercentage) / 12, 0)} kr/mån</Text>
</View>
</View>
</View>
)}
</View>
);
};
_updateSections = activeSections => {
this.setState({ activeSections });
};
render () {
return (
<ScrollView style={styles.backgroundPrimary} showsVerticalScrollIndicator='false'>
<View style={styles.backgroundSecondary}>
<View style={styles.container}>
<Accordion
sections={brfCostRows}
activeSections={this.state.activeSections}
renderHeader={this._renderHeader}
renderContent={this._renderContent}
onChange={this._updateSections}
sectionContainerStyle={styles.accordion}
underlayColor='transparent'
/>
</View>
</View>
</ScrollView>
);
};
};
To fetch data with axios I use the following in other screens but it's not working with the class component:
const { state, fetchUser } = useContext(UserContext);
And in the view:
<NavigationEvents onWillFocus={fetchUser} />
I've tried to remove the render part change the first part to the following but it's complaining about the first function _renderHeader (Unexpected token):
const AnnualFeeScreen = () => {
First of all while converting, class component to functional component with hooks, you must note that, there won't be a this variable inside functional component. Secondly the state inside a functional component would need to be implemented using useState hook
const AnnualFeeScreen () => {
const [activeSections, setActiveSections] = useState([]);
const _renderHeader(section, index, isActive) {
let meanValStatus = '#39D0B5';
if (section.meanDiffVal >= 1.05) {
meanValStatus = '#FCD561';
} else if (section.meanDiffVal < 0.95) {
meanValStatus = '#bbb';
}
return (
<View style={styles.flexRow}>
<View style={{flex:2}}>
<Text style={styles.h6}>{!isActive ? '+' : '-'} {section.title}</Text>
</View>
<View style={styles.flex}>
<Text style={[styles.h6, {textAlign: 'right'}]}>{Math.round((section.titleValue) / 12, 0)} kr/mån</Text>
</View>
<View style={[styles.circleStatus, {backgroundColor: meanValStatus}]}></View>
</View>
);
};
const _renderContent = section => {
return (
<View>
{section.content.map((item, key) =>
<View style={styles.accordionContent} key={key}>
<View style={styles.flexRow}>
<View style={{flex: 2}}>
<Text style={[styles.p, {fontWeight: 'normal'}]}>{item.title}</Text>
</View>
<View style={styles.flex}>
<Text style={[styles.p, {fontWeight: 'normal', textAlign: 'right'}]}>{Math.round((item.value * aptPercentage) / 12, 0)} kr/mån</Text>
</View>
</View>
</View>
)}
</View>
);
};
const _updateSections = activeSections => {
setActiveSections(activeSections);
};
return (
<ScrollView style={styles.backgroundPrimary} showsVerticalScrollIndicator='false'>
<View style={styles.backgroundSecondary}>
<View style={styles.container}>
<Accordion
sections={brfCostRows}
activeSections={activeSections}
renderHeader={_renderHeader}
renderContent={_renderContent}
onChange={_updateSections}
sectionContainerStyle={styles.accordion}
underlayColor='transparent'
/>
</View>
</View>
</ScrollView>
);
};

How to pass Parent Flatlist's Index value to Child Flatlist's onPress function?

How to pass parent Flatlist's index value to child Flatlist's function so I can use it in function and change value by setState.
So how to pass parent Flatlist's index value to child Flatlist's function so I can use it in function and change value by setState.
It starts with a list that built-in state
constructor(props) {
super(props);
this.state = {
list: [
{
question: 'il veicolo ha la gomma forata?',
answers: [
{
radioButtonValue: false,
text: strings.CONFIRMVIEW_yes,
},
{
radioButtonValue: true,
text: strings.CONFIRMVIEW_no,
},
],
},
]
}
}
checkBoxSelection = (item, index) => {
// if (item.radioButtonValue == index) {
// this.list.answers[index].radioButtonValue = true
// }
console.log(this.state.list[0].answers[index].radioButtonValue)
}
_renderItem = ({ item, index }) => {
return (
<View style={styles.cellView}>
<Text style={styles.questionText}>
{item.question.toUpperCase()}
</Text>
<FlatList
data={item.answers}
horizontal={true}
showsHorizontalScrollIndicator={true}
scrollEnabled={true}
bounces={false}
renderItem={this._renderItemOptions}
/>
{/* <View style={styles.yesNoRadioButtonView}>
<View style={styles.yesChekboxView}>
<TouchableOpacity onPress={ () => {console.log("TEST1"); this.checkBoxSelection()} }>
<Image source={(item.answers == index) ? AppImages.radioOn : AppImages.radioOff} style={styles.radioButton} />
</TouchableOpacity>
<Text style={styles.yesNoText}>
{strings.CONFIRMVIEW_yes}
</Text>
</View>
<View style={styles.noRadioButtonView}>
<TouchableOpacity onPress={() => { this.checkBoxSelection.bind(this) }}>
<Image source={(item.answers == 0) ? AppImages.radioOn : AppImages.radioOff} style={styles.radioButton} />
</TouchableOpacity>
<Text style={styles.yesNoText}>
{strings.CONFIRMVIEW_no}
</Text>
</View>
</View> */}
</View>
)
}
_renderItemOptions = ({ item, index }) => {
return (
<View>
<View style={styles.yesNoRadioButtonView}>
<TouchableOpacity onPress={() => { this.checkBoxSelection(item, index) }}>
<View style={styles.yesChekboxView}>
<Image
source={item.radioButtonValue ? AppImages.radioOn : AppImages.radioOff}
style={styles.radioButton}
/>
<Text style={styles.yesNoText}>
{item.text}
</Text>
</View>
</TouchableOpacity>
</View>
</View>
)
}
render() {
return (
<Container>
<Content style={styles.container}>
<FlatList
data={this.state.list}
showsVerticalScrollIndicator={false}
scrollEnabled={false}
bounces={false}
renderItem={this._renderItem}
/>
</Content>
<SafeAreaView>
<TouchableOpacity
style={[LayoutStyle.appBtn1]}
>
<Text style={[LayoutStyle.appBtnText1]}>
{strings.DAMAGE_SURVEY_comeOn.toUpperCase()}
</Text>
</TouchableOpacity>
</SafeAreaView>
</Container>
)
}
In Parent Flatlist's renderItem function
replace
renderItem = { () => {this.renderItemOptions(item, index)}}
with
renderItem={(childData) => this._renderItemOptions(childData, index)}
and then in child Flatlist's renderItemOption function need to get parentIndex with another name.
_renderItemOptions = ({ item, index }, parentIndex) => {
console.log("hello")
return (
<View>
<View style={styles.yesNoRadioButtonView}>
<TouchableOpacity onPress={() => { this.checkBoxSelection(item, index, parentIndex) }}>
<View style={styles.yesChekboxView}>
<Image
source={item.radioButtonValue ? AppImages.radioOn : AppImages.radioOff}
style={styles.radioButton}
/>
<Text style={styles.yesNoText}>
{item.text}
</Text>
</View>
</TouchableOpacity>
</View>
</View>
)
}
Try updating your renderItem prop in your FlatList to explicitly pass the index
renderItem={({item, index}) => this._renderItemOptions(item, index)}

Close modal on click button react native

I have a modal that shown on a button click and the modal is fetched from another component using prop.
In the modal there is a button to close the modal, How to close the modal onclick the button. I have tried but doesn't worked.
//InvalidUser
const InvalidUser = (props) => (
<Modal
visible={props.display}
animationType="slide"
onRequestClose={() => console.log('closed')}
>
<View style={styles.modalBox}>
<View style={{width: 300}}>
<Text style={styles.text}>
{props.data}
</Text>
<TouchableOpacity
onPress={() =>
this.closeModal()
}>
<Text style={styles.buttonOk}>Ok</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
);
//Login
export default class LoginFirst extends Component {
constructor(props) {
super(props);
this.state = {
email: '',
modalVisible: false
};
}
nextBtn = () => {
let reg = /^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/;
if (this.state.email !== '') {
if (reg.test(this.state.email) === false) {
}
else {
this.setState({modalVisible: true});
}
}
}
render() {
let notRegistered = this.state.email+' is not recognized as a registered user. Please contact us for further assistance.';
return (
<View style={styles.container}>
<ScrollView contentContainerStyle={styles.scroller}>
<View
style={styles.inputSection}
>
<Text style={styles.label}>Email Address:</Text>
<View style={styles.section}>
<Image
style={styles.icon}
source={require('../../../../assets/user.png')}
/>
<TextInput
style={styles.input}
placeholder='johnsmith#gmail.com'
underlineColorAndroid='transparent'
onChangeText={(text) => this.setState({email:text})}
/>
</View>
<TouchableOpacity
style={styles.button}
onPress={() =>
this.nextBtn()
}
>
<Text style={styles.next}>Next</Text>
</TouchableOpacity>
</View>
</ScrollView>
<InvalidUserModal
data={notRegistered}
display={this.state.modalVisible}
/>
</View>
);
}
}
The above code is perfectly displaying the modal, but I cannot close the modal. Is there any way to close.
Please have a look into below image.
from parent component, create closeModal function and pass it to InvalidUserModal
closeModal = () => {
this.setState({modalVisible: false});
}
<InvalidUserModal
data={notRegistered}
display={this.state.modalVisible}
closeModal={this.closeModal}
/>
and call it inside InvalidUserModal on press the button
<TouchableOpacity onPress={props.closeModal}>
<Text style={styles.buttonOk}>Ok</Text>
</TouchableOpacity>
For parent, pass the closeModal method as a props to your component
class LoginFirst extends Component {
closeModal = () => {
this.setState({modalVisible: false});
}
render() {
return (
<InvalidUserModal
data={notRegistered}
display={this.state.modalVisible}
closeModal={this.closeModal}
/>
)
}
}
For your modal component
<Modal
visible={props.display}
animationType="slide"
onRequestClose={() => console.log('closed')}
>
<TouchableOpacity onPress={props.closeModal}>
<Text style={styles.buttonOk}>Ok</Text>
</TouchableOpacity>
</Modal>

How to open React Native Modal with JUST state change (No onPress trigger)?

I want a RN Modal to pop up on a Dropdown (RN Material Dropdown) onChangeText call. However, even though the this.state.modalVisibleTwo is changed to true through this function, the modal doesn't show up on the state change.
Is there a way to directly trigger the Modal opening.
I attempted conditional rendering based on this.state.modalVisibleTwo with a Modal that's visible={true} and still nothing.
<Modal
animationType='slide'
presentationStyle='overFullScreen'
transparent={true}
visible={this.state.modalVisibleTwo}
ref={component => this.inputModal = component}
onRequestClose={() => {
// console.log('Modal has been closed.');
}}>
<View style={styles.inputContainer}>
<View style={styles.innerContainer}>
<Text style={styles.howMany}>test</Text>
<TextInput
style={styles.textInput2}
underlineColorAndroid={'rgba(0,0,0,0)'}
maxLength={3}
autoCorrect= {false}
clearButtonMode="while-editing"
keyboardType="numbers-and-punctuation"
ref={component => this._textInput2 = component}
onChangeText={(q) => this.setState({currentQuantity: q})}
placeholder= {strings.enter}/>
<View style={{flexDirection: 'row'}}>
<Button
onPress={() => {
this.setModalVisibleTwo(false);
}}>
{strings.close}
</Button>
<TouchableOpacity style={styles.Button2} onPress={()=> {this.addToCart(order, orderNumber, isCartEmpty)}}>
<Text style={styles.addToOrderButtonText2}>{strings.add}</Text>
</TouchableOpacity>
</View>
</View>
</View>
</Modal>
<TouchableWithoutFeedback onPress={()=>Keyboard.dismiss()} accessible={false}>
<View>
<Text style={styles.bodyTitle}>{strings.schedTitle}</Text>
<View style={styles.dropdownContainer}>
<Dropdown
label={strings.select}
data={this.state.services}
itemTextStyle={{fontFamily: 'Heiti TC', }}
containerStyle={styles.dropDown}
baseColor={'#002d62'}
itemColor={'rgba(0, 0, 0, .54)'}
selectedItemColor={'#002d62'}
itemPadding={9}
itemCount={7}
dropdownPosition={-8}
pickerStyle={{width: screenWidth*(3/4), marginLeft: screenWidth*0.032}}
onChangeText={(val)=>{this.updateView(val)}}
/>
<TouchableOpacity style={styles.Button} onPress={()=> {this.addToCart(order, orderNumber, isCartEmpty)}}>
<Text style={styles.addToOrderButtonText}>{strings.ok}</Text>
</TouchableOpacity>
</View>
<TouchableOpacity onPress={()=>{this.setModalVisibleTwo(true)}}>
<Text style={styles.modalTitle1}>{strings.which}</Text>
</TouchableOpacity>
</View>
</TouchableWithoutFeedback>
updateView(val){
//this.inputModal.open();
if(val == strings.dobox || val == strings.pubox){
// How Many Boxes
this.setState({modalVisibleTwo: true, currentService: val, isBox: strings.isBox, updatedDrop: false});
} else if(val == strings.dobar || val == strings.pubar){
// How Many Barrels
this.setState({modalVisibleTwo: true, currentService: val, isBox: strings.isBarrel, updatedDrop: false});
}
else{
// Nothing
this.setState({currentService: val, currentQuantity: '', isBox: '', updatedDrop: false});
}
}
I expect the modal to pop up after a modalVisibleTwo state change to true after onChangeText call in Dropdown, but the actual output is a state change and no modal pop up.

How to do the multi Button onPress functions in one common component - React native

I have a component call ButtonLayout.js
export const ButtonLayout = () => {
return (
<View style={styles.row}>
<TouchableOpacity >
<Text>Book Now</Text>
</TouchableOpacity>
<TouchableOpacity >
<Text>Schedule</Text>
</TouchableOpacity>
</View>
)
}
and i have import this component to another common component called mapComponent and it look like following.
return (
<View style={styles.container}>
<MapView
provider={MapView.PROVIDER_GOOGLE}
style={styles.map}
region={this.props.region}
>
<MapView.Marker
coordinate={this.props.region}
pinColor='green'
/>
</MapView>
<ButtonLayout style={{ marginBottom: 5 }} />
</View>
);
so my question is how can i handle the onPress() function of the buttons in ButtonLayout.js from index.js ?
Make your ButtonLayout component accept callback props, like so:
export const ButtonLayout = ({onBook, onSchedule}) => (
<View style={styles.row}>
<TouchableOpacity onPress={onBook}>
<Text>Book Now</Text>
</TouchableOpacity>
<TouchableOpacity onPress={onSchedule}>
<Text>Schedule</Text>
</TouchableOpacity>
</View>);
Then, pass the callbacs in the parent component’s render function as props
<ButtonLayout onBook={…} onSchedule={…} />
Don’t forget to bind the context to the callbacks
In your button Buttonlayout.js define like this:
<TouchableOpacity onPress={() => this.props.onPress()}>
<Text>Book Now</Text>
</TouchableOpacity>
And define onPress function on each file you use this component just like.
<ButtonLayout style={{ marginBottom: 5 }} onPress={() => {'your logic..'}}/>
Define your callback variables in ButtonLayout and add them to your touchables.
export const ButtonLayout = ({ onBookPress, onSchedulePress }) => {
return (
<View style={styles.row}>
<TouchableOpacity onPress={onBookPress}>
<Text>Book Now</Text>
</TouchableOpacity>
<TouchableOpacity onPress={onSchedulePress} >
<Text>Schedule</Text>
</TouchableOpacity>
</View>
)
}
Define your callbacks in index:
indexOnBookPress = () => {
...do something
}
indexOnSchedulePress = () => {
...do something
}
return (
<View style={styles.container}>
<MapView
provider={MapView.PROVIDER_GOOGLE}
style={styles.map}
region={this.props.region}
>
<MapView.Marker
coordinate={this.props.region}
pinColor='green'
/>
</MapView>
<ButtonLayout style={{ marginBottom: 5 }} onBookPress={this.indexOnBookPress} onSchedulePress={this.indexOnSchedulePress} />
</View>
);

Resources