I want dynamic multiple date / time pickers.
I tried a piece of code but every time I datepicker is open for some other item and not the one clicked.
Versions
react-native 0.47.1
react-native-modal-datetime-picker ^4.11.0
Code
import React, { Component } from 'react';
import {
Text, View, StyleSheet, TouchableOpacity
} from 'react-native';
import {
Tile as ShoutemTile, Text as ShoutemText, Title as ShoutemTitle,
Row as ShoutemRow, Subtitle as ShoutemSubtitle, Button as ShoutemButton,
Icon as ShoutemIcon
} from '@shoutem/ui';
import { Content, Left, Right, Body, Button, Icon, List, ListItem } from 'native-base';
import Moment from 'moment';
import DateTimePicker from 'react-native-modal-datetime-picker';
import * as utils from '../../utils';
import { Loader, CustomDialog } from '../../components/common';
export default class OfferForm extends Component {
constructor(props) {
Moment.locale('en');
super(props);
this.state = {
offer_name: this.props.offer_name,
offer_id: this.props.offer_id,
form: this.props.form,
color: this.props.color,
isProcessing: false,
showFinished: false,
error: false,
successMessage: '',
isDateTimePickerVisible: false
};
for (let i = 0; i < this.state.form.length; i++) {
this.state[this.state.form[i].id] = null;
}
this.confirm = this.confirm.bind(this);
this.cancel = this.cancel.bind(this);
}
confirm() {
// Send request to server
this.setState({ isProcessing: true });
utils
.requestConference(this.state.selectedItems)
.then(res => {
try {
this.setState({ isProcessing: false });
if (res.status) {
if (res.status === 'success') {
this.setState({
successMessage: res.message,
showFinished: true
});
} else {
this.setState({
successMessage: res.message,
error: true,
showFinished: true
});
}
}
} catch (error) {
console.log(error);
}
});
}
cancel = () => this.popupDialog.dismiss();
showDateTimePicker = () =>
this.setState({ isDateTimePickerVisible: true })
hideDateTimePicker = () =>
this.setState({ isDateTimePickerVisible: false })
handleDatePicked = (id, type, date) => {
let value;
if (type === 'date') {
value = Moment(date).format('DD MMM YYYY').toString();
} else {
value = Moment(date).format('hh:mm A').toString();
}
this.setState({
[id]: value
});
console.log(this.state);
this.hideDateTimePicker();
};
render() {
const form = this.state.form;
if (this.state.loading) {
return (
<Loader text='Please wait...' color={this.state.color} />
);
} else if (this.state.isProcessing) {
return (
<Loader text='Sending request...' color={this.state.color} />
);
} else if (this.state.showFinished) {
return (
<CustomDialog
title='Thank You'
error={this.state.error}
message={this.state.successMessage}
color={this.state.color}
/>
);
}
const uiElements = [];
for (let i = 0; i < form.length; i++) {
// Define type
let formType;
if (form[i].type === 'date') {
formType = (
<ShoutemRow key={form[i].id + (2 * (i + 1))}>
<ShoutemButton
onPress={this.showDateTimePicker}
style={{
flex: 1,
borderColor: 'grey',
borderWidth: 1,
borderRadius: 3,
padding: 5,
justifyContent: 'flex-start'
}}
>
<ShoutemIcon name="add-event" style={{ color: 'grey' }} />
<Text style={{ color: 'grey' }}>
{this.state[form[i].id]}
</Text>
</ShoutemButton>
<DateTimePicker
key={form[i].id}
date={new Date()}
mode={'date'}
isVisible={this.state.isDateTimePickerVisible}
onConfirm={this.handleDatePicked.bind(this, form[i].id, 'date')}
onCancel={this.hideDateTimePicker}
/>
</ShoutemRow>
);
} else if (form[i].type === 'time') {
formType = (
<ShoutemRow key={form[i].id + (2 * (i + 1))}>
<ShoutemButton
onPress={this.showDateTimePicker}
style={{
flex: 1,
borderColor: 'grey',
borderWidth: 1,
borderRadius: 3,
padding: 5,
justifyContent: 'flex-start'
}}
>
<ShoutemIcon name="add-event" style={{ color: 'grey' }} />
<Text style={{ color: 'grey' }}>
{this.state[form[i].id]}
</Text>
</ShoutemButton>
<DateTimePicker
key={form[i].id}
date={new Date()}
mode={'time'}
isVisible={this.state.isDateTimePickerVisible}
onConfirm={this.handleDatePicked.bind(this, form[i].id, 'time')}
onCancel={this.hideDateTimePicker}
/>
</ShoutemRow>
);
} else if (form[i].type === 'text') {
//
} else if (form[i].type === 'count') {
//
} else if (form[i].type === 'comment') {
//
}
uiElements.push(
<ShoutemTile style={{ padding: 5 }} key={'parent_' + form[i].id + (2 * (i + 1))}>
<ShoutemText style={{ color: '#000000' }}>{form[i].field}</ShoutemText>
{formType}
</ShoutemTile>
);
}
return (
<View style={{ flex: 1 }}>
<View style={{ flex: 0.9 }}>
<Content>
{uiElements}
</Content>
</View>
<View style={{ flex: 0.1, position: 'absolute', left: 0, right: 0, bottom: 0 }}>
<Button
full
onPress={() => {
alert('hi'); //eslint-disable-line
}}
style={{
flex: 1,
backgroundColor: this.state.color,
borderColor: this.state.color
}}
>
<ShoutemTitle style={{ color: '#FFFFFF' }}>Claim</ShoutemTitle>
</Button>
</View>
</View>
);
}
}
Hello @princenaman
Given the fact that this component uses a modal, you should use only a single instance of it and simply adapt its prop to the interested values.
Just take this out of the loop:
<DateTimePicker
key={form[i].id}
date={new Date()}
mode={'time'}
isVisible={this.state.isDateTimePickerVisible}
onConfirm={this.handleDatePicked.bind(this, form[i].id, 'time')}
onCancel={this.hideDateTimePicker}
/>
And set the interested dates programmaticaly (keep them in the state).
For example you could change it to something like this:
showDateTimePicker = (formIdInDatePicker) =>
this.setState({ isDateTimePickerVisible: true, formIdInDatePicker: formIdInDatePicker })
hideDateTimePicker = () =>
this.setState({ isDateTimePickerVisible: false, formIdInDatePicker: null })
handleDatePicked = (type, date) => {
let value;
if (type === 'date') {
value = Moment(date).format('DD MMM YYYY').toString();
} else {
value = Moment(date).format('hh:mm A').toString();
}
this.setState({
[formIdInDatePicker]: value
});
console.log(this.state);
this.hideDateTimePicker();
};
...
<DateTimePicker
date={new Date()}
mode={'time'}
isVisible={this.state.isDateTimePickerVisible}
onConfirm={this.handleDatePicked.bind(this, 'time')}
onCancel={this.hideDateTimePicker}
/>
Works like a charm 馃槃
Most helpful comment
Hello @princenaman
Given the fact that this component uses a modal, you should use only a single instance of it and simply adapt its prop to the interested values.
Just take this out of the loop:
And set the interested dates programmaticaly (keep them in the state).
For example you could change it to something like this: