MUI Datepicker onChange event working with manual input but not when clicking date - datepicker

I've been toying around with this for a while to no avail.
When the user inputs a date manually into the text field, that onChange event fires and everything works as I want it to. When the user clicks on a date from from datepicker, nothing at all happens.
I'm still getting used to using MUI fields in Controllers to suit React Hook Form, but I'm not sure what I'm doing incorrectly.
const { handleSubmit, control, register } = useForm();
const [selectedDate, setSelectedDate] = React.useState(null);
const handleDateChange = (date) => {
console.log(date)
setSelectedDate(date);
};
<form onSubmit={handleSubmit(submitForm)}>
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<Controller
control={control}
name={"newEffectiveDate"}
defaultValue={null}
render={() => (
<KeyboardDatePicker
inputVariant="outlined"
disableToolbar
format="MM/dd/yyyy"
margin="normal"
id="date-picker-inline"
label="Date picker inline"
value={selectedDate}
onChange={date => handleDateChange(date)}
KeyboardButtonProps={{
"aria-label": "change date",
}}
/>
)}
/>
</MuiPickersUtilsProvider>
</form>
Any help would be much appreciated!

Turns out, I just needed to add the autoOk prop to the KeyboardDatePicker component...

Related

How to handle state in Material UI Data Grid's components

I'm attempting to add search functionality to a data grid component. In order to achieve this, I'm adding an input element to the table using the components.header prop as follows (I've omitted irrelevant code):
const Table = () => {
const filterRows = (rows) => {
return rows;
};
const [searchTerm, setSearchTerm] = useState("");
const Header = () => (
<input
value={searchTerm}
onChange={(event) => setSearchTerm(event.target.value)}
/>
);
return (
<div style={{ height: 500 }}>
<DataGrid
rows={searchTerm ? filterRows(orders) : orders}
columns={orderColumns}
components={{
header: () => <Header />
}}
/>
</div>
);
};
The issue I'm having is that the input element loses focus each time a character is entered into the input in the header. Presumably, this is because it updates state, which triggers a re-render. This makes it impossible to share and access state of anything contained inside the Data Grid's components because it requires a React.FC argument and won't accept a ReactElement so the input is always re-rendered.
Am I missing something or is this actually not possible with Material UI's Data Grid? It seems like a pretty expected use-case to have something stateful in the header that we'd want to access like a controlled input component in order to use it as a kind of "Tool bar" as mentioned in the Material UI docs.
I've created a code sandbox to replicate the issue here: https://codesandbox.io/s/compassionate-keldysh-z995k?file=/src/App.js:246-726.
Cheers.

building a basic search bar Material-UI

I want to build a really basic search bar with a search icon (similar to the one on Material-UI ) & invoke a function with the current value of the search field whenever the user hits enter or click on the search enter. I am new to Material-UI & I'm struggling to find my way through the different text fields elements.
I currently have this code
import Input from '#material-ui/core/Input';
class ...somecode
...somecode
constructor(props) {
super(props);
this.state = {
resources: [],
value: '',
};
}
handleChange(event) {
console.log(event.target.value);
this.setState({ value: event.target.value });
}
search(/* access value upons enter/ search icon click */) { <--------------------------
}
...some code
return (
<form id="search">
<Input type="text" value={value} onChange={(event) => { this.handleChange(event); }} placeholder="Search..." autoFocus fullWidth />
</form>
);
p.s: I had a really hard time fiddling around with all the APIs and options available in the input suite (I highly suggest an explanation of how they are related in the docs)

How to submit a form on input field onBlur event in ReactJS?

I have multiple form in a Screen. Need to submit form while onBlur event calling without using ref, because i have multiple and dynamic forms.
You may add onBlur event, get access to DOM-element Form and then do submit 'form.submit()':
const myForm = () =>
<input onBlur={(e) => {
// if click occurs outside of element
if(!e.relatedTarget || (e.target.form !== e.activeTarget))
//attention: your page will reload every such instant submission
e.target.form.submit();
}
}} ... (other props) >
...
</form>
Or you need to use
<form onSubmit={(e) => {
e.preventDefault();
...
}>
<input onBlur={(e) => {
...
e.target.form.requestSubmit();
} />
...
the detail of this solution are here Here is my question

How to disable past dates in material-ui Date picker?

I'm using material-ui Date-Picker. How to disable past days before today's date?
import React from 'react';
import DatePicker from 'material-ui/DatePicker';
function disablePastDays(date) {
//code here to disable past days
}
const calendar = () => (
<div>
<DatePicker shouldDisableDate={disablePastDays}/>
</div>
)
material-ui's DatePicker accepts minDate prop. So you might want this:
const today = new Date();
<DatePicker minDate={today}/>
Use disablePast.
<DatePicker
disablePast
/>
They have it since v1.0.0-beta.10.
We can give minDate as props to the DatePicker material UI component
Create a state using usestate and then pass the state value into the props as below
const [startMinDate, setStartDate] = useState(new Date())
<DatePicker
required
label="Date"
disablePast
minDate = {startMinDate}
/>
I am using import DatePicker from '#mui/lab/DatePicker'; library of version "#mui/lab": "^5.0.0-alpha.66"
Below code works fine for me
<DatePicker
disablePast
value={checkout.rideDate}
onChange={(newValue) => { // your code of onChange functionality}
/>
}
/>

DatePicker date input with custom format

I want to stote dates in my state using redux-form. I use react-datepicker. To make the datepicker compatible with my redux-form i write:
import React, { PropTypes } from 'react';
import DatePicker from 'react-datepicker';
import moment from 'moment';
import 'react-datepicker/dist/react-datepicker.css';
const MyDatePicker = ({ input, meta: { touched, error } }) => (
<div>
<DatePicker
{...input} dateFormat="YYYY-MM-DD"
selected={input.value ? moment(input.value) : null}
/>
{
touched && error &&
<span className="error">
{error}
</span>
}
</div>
);
MyDatePicker.propTypes = {
input: PropTypes.shape().isRequired,
meta: PropTypes.shape().isRequired
};
export default MyDatePicker;
The problem is that when i choose date i want it to show as DD-MM-YYYY but i want the date to be saved in my state with the YYYY-MM-DD HH:MM:SS format. How to do this? I use the moment's format function but it did not seem to work
You should use the value lifecycle methods that redux-form provides for this.
Use parse to format the value coming from react-datepicker for storage and format to parse the value from the store back for react-datepicker to present it. Example:
function formatDateForInput(storedDate) {
// the returned value will be available as `input.value`
return moment(pickedDate).format('right format for your input')
}
function parseDateForStore(pickedDate) {
// the returned value will be stored in the redux store
return moment(storedDate).format('desired format for storage')
}
<Field
component={ MyDatePicker }
format={ formatDateForInput }
parse={ parseDateForStore }
/>
If this does not work for your, I would recommend checking if you need to put a custom onChange handler between the DatePicker and input prop provided by redux-form. Because it could be that the values DatePicker is using to call onChange are ones that redux-form does not understand. Like this:
const MyDatePicker = ({ input, meta: { touched, error } }) => {
const onChange = event => {
const pickedDate = event.path.to.value;
input.onChange(pickedDate);
}
return (
<div>
<DatePicker
dateFormat="YYYY-MM-DD"
selected={input.value ? moment(input.value) : null}
onChange={ onChange }
/>
{
touched && error &&
<span className="error">
{error}
</span>
}
</div>
);
}
MyDatePicker.propTypes = {
input: PropTypes.shape().isRequired,
meta: PropTypes.shape().isRequired
};
export default MyDatePicker;
Hope this helps!
If i am understanding correct you just need 2 different formats for same date one on UI and other to save ? moment(date).format('DD-MM-YYYY') and moment(date).format('YYYY-MM-DD HH:MM:SS') will give you both formats date.
Just use the prop dateFormat="dd/MM/yyyy"
Example :
<DatePicker
selected={startDate}
onChange={date => handleChange(date)}
dateFormat="DD/MM/YYYY"
/>
I used the below props -mask, inputFormat and format - to change the default format to "yyyy-MM-dd" format.
The format code "yyyy-MM-dd" is important, play around this to find the desired format.
Example:
<LocalizationProvider dateAdapter={AdapterDateFns} >
<DatePicker
label="SomeDate"
{...register("details_received_date")}
mask="____-__-__"
inputFormat="yyyy-MM-dd"
format="yyyy-MM-dd"
value={someDate}
onChange={(newValue) => {setSomeDate(newValue);}}
renderInput={(params) => <TextField {...params} />}
/>
</LocalizationProvider>
This will display in the front end and provide the value as well in the desired format.
Hope this helps.
Try this
inputFormat="DD/MM/YYYY"
const [value, setValue] = useState(null);
<LocalizationProvider dateAdapter={AdapterDayjs}>
<DatePicker
label="DatePicker Example"
value={value}
onChange={(newValue) => {
setValue(newValue);
}}
renderInput={(params) => <TextField {...params} />}
inputFormat="DD/MM/YYYY"
/>
</LocalizationProvider>