How to externally set calendar value in primereact? - reactjs

I added a couple buttons to the calendar footer, just to set the value to a specific date. The date is declared with usestate, and when I click the button, the value of the date variable is set appropriately, I also see the calendar UI changing the highlighted day, although I need to use setState() on the calendar to move the UI to the new month/year if that's required. The overall structure is like this:
const [date, setDate] = useState<Date | Date[]>(new Date());
const presetDate = new Date(2021,4,2);
const calendar = useRef<Calendar>(null);
const setCalendarValue = (targetDate: Date) => {
setDate(targetDate);
let calendarState = calendar.current?.state;
calendar.current?.setState({
focused: calendarState?.focused ?? false,
overlayVisible: calendarState?.overlayVisible ?? false,
viewDate: targetDate
});
}
const calendarFooter = () => {
return (
<>
<Button label="Preset date" onClick={() => setCalendarValue(presetDate) }
</>
)
}
retun(
<>
<Calendar
ref={calendar}
field="date"
label="Date"
id="date"
minDate={new Date(2000,0,1)}
value={date?? undefined}
onChange={(e) => setDate(e.value || new Date())}
/>
</>
);
Everything works except that the textbox with the date does not show the newly assigned date until the calendar is closed, then reopened, and the button clicked a second time. Specifically in this order.
So far as I understand, I need to cause the input event on the calendar, but I can't seem to find out how it's done, and the event dispatcher is not exposed, even though I do see it in the source of the calendar component itself.

Related

Allowing Null Value for React-Native-DateTimePicker

I have a React Native application with a form for entering data. One of the fields is a DateTime value, but is optional. In other words, the user can choose a date if they want one, but can leave it blank/null if the field is not relevant.
However, when I assign null to the date prop of the DateTimePicker, I get an exception that null is not an object. How can allow the user to choose a date if they want to, but leave it "null" if they don't want a date in that field.
<DateTimePicker
isVisible={isDatePickerVisible}
mode={mode}
onConfirm={handleConfirm}
onCancel={hideDatePicker}
date={selectedDate}
onBlur={onBlur}
/>
Is there a property I am missing? Is there a different component I can use to accomplish this?
Notice that
Please note that this library currently exposes functionality from UIDatePicker on iOS and DatePickerDialog + TimePickerDialog on Android, and CalendarDatePicker +TimePicker on Windows.
These native classes offer only limited configuration, while there are dozens of possible options you as a developer may need. It follows that if your requirement is not supported by the backing native views, this library will not be able to implement your requirement. When you open an issue with a feature request, please document if (or how) the feature can be implemented using the aforementioned native views. If those views do not support what you need, such feature requests will be closed as not actionable.
as provided in the react-native-datetimepicker documentation.
The date prop that you are using is one of them. For iOS it exposes a field of UIDatePicker which is
The initial date that the date picker will display. Defaults to the current date, but you can set a custom value. This attribute is equivalent to setting the date property programmatically.
However, as stated in the react-native-datetimepickerdocumentation its usage is limited. The correct prop that we need to use is the value prop which
Defines the date or time value used in the component.
This field is required. We cannot unset it. There will always be some default value which needs to be explicitly set initially.
However, what you want to achieve can be done differently. You need to handle the form value yourself in a state of the form. Thus,
const [date, setDate] = useState()
The state date in your form is initially undefined. The value prop of your DateTimePicker is not.
The DateTimePicker gets an onConfirmMethod. If that is fired set your date state to the value prop passed to the onConfirmMethod as follows
const onConfirm = (selectedDate) => {
setDate(selectedDate)
}
<DateTimePicker
isVisible={isDatePickerVisible}
mode={mode}
onConfirm={onConfirm}
onCancel={hideDatePicker}
value={date}
onBlur={onBlur}
/>
}
Usually you want the user to allow to delete the field afterwards. You need to implement this yourself, since value cannot be unset. If the selected date is visualized in some kind of InputField, then this can easily be done.
The data of your form is then decoupled from your DateTimePicker value prop. I'm afraid that there is no other way, at least with this library.
Thank you to #david-scholz for the insight into the react-native-datetimepicker library and the lack of null support. With that said, his answer doesn't provide the functionality requested.
I manage to implement it with a custom component which wraps the react-native-modal-datetimepicker library. The basic idea is to use the picker only when the user wants to pick a date.
To accomplish this:
text is used to display the current value or "No Date Selected".
When the user clicks the text, the date time picker is shown to let them select a date
There is a button to click if the user wants to clear the date and go back to null
Note: This was intended to be used with Formik (in my use case) so the date / time value being passed back is in string format (it works better with Formik).
Here is the code, in case anyone can use it. It should be considered MIT License.
import React, { useState } from 'react';
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import DateTimePickerModal from 'react-native-modal-datetime-picker';
import moment from 'moment';
const isNullOrWhitespace = ( input ) => {
return !input || !input.trim();
}
export default function NullableDatePicker (props) {
const {value, onChange, onBlur} = props;
const [isDatePickerVisible, setDatePickerVisibility] = useState(false);
const [selectedDate, setSelectedDate] = useState(isNullOrWhitespace(value) ? new Date() : new Date(value));
const [hasDate, setHasDate] = useState(isNullOrWhitespace(value) ? false : true);
const showDatePicker = () => {
setDatePickerVisibility(true);
};
const hideDatePicker = () => {
setDatePickerVisibility(false);
};
const handleConfirm = date => {
hideDatePicker();
setHasDate(true);
setSelectedDate(new Date(date));
onChange(valueToString(date));
};
const valueToString = selectedDate => {
return moment(selectedDate).format('YYYY-MM-DD');
}
const clearDate = () => {
setHasDate(false);
onChange('');
}
return (
<View>
<View style={styles.fixToText}>
<Text style={styles.dateText} onPress={showDatePicker}>{hasDate ? valueToString(selectedDate) : 'No Date Selected'}</Text>
<Text> </Text>
<TouchableOpacity
title="Clear"
onPress={() => clearDate()}
disabled={!hasDate}
style={styles.button}
>
<Text>Clear</Text>
</TouchableOpacity>
</View>
<DateTimePickerModal
isVisible={isDatePickerVisible}
mode='date'
onConfirm={handleConfirm}
onCancel={hideDatePicker}
date={selectedDate}
onBlur={onBlur}
/>
</View>
);
}
const styles = StyleSheet.create(
{
fixToText: {
flexDirection: 'row'
},
button: {
alignItems: "center",
backgroundColor: "lightblue",
padding: 5,
height: 30,
width: 50
},
dateText:{
height: 30,
textAlignVertical: 'center'
}
}
)

Modal shows previous data

I have a little "bug" here. I have a modal that receives a text, that corresponds a message to show, a state and a property to restore the values of the states when the modal close. In the main, I have three states, each one represents different situations and each show a unique message. The problem occurs when I run the app, choose a date in a datetimepicker, evaluate that in a function, and then I sent that result in a conditional, if "result" is in a determined range -> I set a specific state, else, set another state. Once a state is true, the modal opens with the specific text.
The problem take place when the modal open, the information correspond to a previous "result". I tried to debug with console logs, and I saw that the states doesn't update.
Is it possible that the states take a time to update? Or could be a problem with the cache of the device?
I attach the code below.
Here are the definition of the states
const [modalVisible1, setModalVisible1] = useState(false)
const [modalVisible2, setModalVisible2] = useState(false)
const [modalVisible3, setModalVisible3] = useState(false)
This is the conditional that I explained. picker_value is a variable that take an option from a menu by the user.
const setModal = () => {
(picker_value ===2 && (result>6 && result<150)) ? setModalVisible1(true) : setModalVisible2(true)
if(picker_value == 3)
setModalVisible3(true)
}
And finally, I have this expression (one for each state), to show the modal with the respective message
{modalVisible1 && <MyModal
message={"Test123"}
state={modalVisible1}
restore={resetModal}
/>
}
And I detach the modal
export const MyModal = (props) => {
return (
<Modal visible={props.state}
transparent={true}
animationType='slide'
>
<View style={styles.container}>
<Text>{props.message}</Text>
<TouchableOpacity onPress={() => props.restore()}>
</TouchableOpacity>
</View>
</Modal>
);
EDIT: onChange Method. Date is the current day, and days is a state that saves the result from process_days (calculates the diff between 2 dates)
const [days, setDays] = useState(0)
const onChange = (event, selectedDate) => {
setShow(Platform.OS === 'ios')
setSelectedDay(selectedDate)
setDays(process_days(date, selectedDate))
setPickerValue(formData.pickerValue)
setModal()
}
Reset states
const resetModal = () => {
setModalVisible1(false)
//same for each modal
}

Proper way to change calendar date clear icon in DatePicker for AntD

I want to change the clear icon of a date picker from the ant design framework.
Is it possible ?
Reason - I want to reset the date to today when it clicks. So close-icon is not appropriate.
Since antd uses rc-picker to create DatePicker component, you can use clearIcon attribute to customize clear icon, but since you need to reset datePicker's value to today with click on clear, you need to do a bit more to handle this requirement, here is an example:
function PickerWithCustomClear() {
const [date, setDate] = React.useState(null);
const [shoudlReset, setShouldReset] = React.useState(false);
const onChange = (date) => {
setDate(date);
if (!date && shoudlReset) {
setDate(moment());
setShouldReset(false);
}
};
return (
<DatePicker
onChange={onChange}
allowClear={true}
value={date}
clearIcon={
// you can use every element here
<SyncOutlined onMouseDown={(e) => setShouldReset(true)} />
}
/>
);
}
I've implemented an example you can find it Here.

How to reset my filter options to their initial blank state? React

I have some input boxes, select drop down, and date picker that are not being reset like I thought they would. Let's start with the input box and select drop down. Here is their code:
<StyledInput
onChange={handleSearchChange}
value={searchText}
placeholder={"Search..."}
/>
<SelectDropDown
isClearable={false}
isSearchable={false}
strict={true}
allowInvalid={false}
getOptionLabel={opt => opt.name}
getOptionValue={opt => opt.value}
value={searchOptions.find(opt => opt.value === searchCol)}
options={searchOptions}
onChange={value => {
handleColSelect(value);
}}
/>
Notice the handleSearchChange and handleColSelect:
const handleColSelect = value => {
setSearchCol(value.value);
};
const handleSearchChange = event => {
setSearchText(event.target.value);
};
I have a button that I want to reset these to their initial states (i.e. get rid of text in the input box, and reset the SelectDropDown).
I've tried doing so:
const clearFilters = () => {
setSearchText(undefined);
setStartDate(undefined);
setEndDate(undefined);
setSearchCol(undefined);
};
And in my button, simply this:
<GreenOutlineButton
onClick={() => {
clearFilters();
}}
>
Clear Filters
</GreenOutlineButton>
There is another part to this to remove the queryParams that are set, and my button does so- however, it does not take away the text or reset the dropdown. Any ideas here?
From the look of it, setSearchText("") should work fine. For the SelectDropDown, you need to add one more entry to the options which will be your default entry. You can do this as follows:
options={[...searchOptions,{label:"Placeholder", value: null}]}
Then, inside clearFilters, use:
setSearchCol(null)
This should give you the desired result. Let me know if this works.

Clear react-datepicker on form reset in react-final-form

I'm using react-final-form and react-datepicker. I also have a select for year. Start and end dates should be set to January 1 and December 31 of the default year. When a new year is selected I would like to reset the form, clear selected dates and input values of both datepickers and set them to January 1 and December 31 of the selected year respectively.
Here is the link to my codesandbox https://codesandbox.io/s/react-datepicker-clear-cxlxh.
So far, I have a custom component for react-datepicker which works with react-final-form. Start and end dates are set to January 1 and December 31 of the default year.
DatePicker component:
const DatePickerWrapper = props => {
const { input, label, minDate, maxDate } = props;
const [startDate, setStartDate] = useState(input.value);
return (
<div>
<label>{label}</label>
<DatePicker
selected={startDate}
minDate={minDate}
maxDate={maxDate}
onChange={value => {
setStartDate(value);
props.input.onChange(value);
}}
onBlur={props.input.onBlur}
onFocus={props.input.onFocus}
value={props.input.value}
/>
</div>
);
};
And Field where it is used:
<Field
name="startDate"
initialValue={isoDate(minDate(values.year.value))}
component={DatePickerWrapper}
minDate={minDate(values.year.value)}
maxDate={
values.endDate ? values.endDate : maxDate(values.year.value)
}
/>
Here is my component for resetting the form:
<Field name="year" subscription={{}}>
{({ input: { onChange } }) => (
<OnChange name="year">
{value => {
form.reset({
...initialValues,
year: value
});
}}
</OnChange>
)}
</Field>
So my questions are:
How can I clear react-datepicker and its input value on form reset? There is a clear() function, but I couldn't make it to work.
How can I then set the dates to January 1 and December 31 of the selected year? I've added initialValue for each field and the values of the form are updated. But the inputs' values stay the same.
You have few issues in the form.
You are giving initial values to you dates twice. Once at the top and then again as the props. This is causing the render to go into infinite loop. Have moved all the form initialization to top in object
const initialValues = {
year: { value: "2019", label: "2019" },
startDate: isoDate(minDate("2019")),
endDate: isoDate(maxDate("2019")),
amount: ""
};
When you are doing form.reset for the year, at that place you can reset the value for the start date and end date
form.reset({
...initialValues,
year: value,
startDate: isoDate(minDate(value.value)),
endDate: isoDate(maxDate(value.value))
});
From the given code, I didn't see any requirement for usestate in datepicker.jsx as it seemed to be getting handled by the form. And so have removed it.
I have updated the code in the Sandbox.
Have a look at it and let me know if any thing is missed or you have any doubts.
The value is stored in this.component_name.current.state, so use an assignment operator and assign an empty string to it. do this operation in a callback of a state change operation (either a setState or a useState). Should work. worked for me.
this.startdate.current.state.value = "";
this.startdate.current.state.inputValue = "";

Resources