Components lifecycle
This page explains when the onChange, onAccept, and onClose callbacks are called.
Lifecycle on simple fields
The field components have an internal state controlling the visible value.
It will only call the onChange callback when:
- the user completes all sections of a field. The value reflects the field.
- when the date is not parseable, the
onChangeprop receives anInvalid Date(for example, if the year is less than "100" in case ofdayjs).
- when the date is not parseable, the
- the user cleans at least one or all sections of a completed field. The value equals
null.
The example below shows the last value received by onChange.
Value: null
Lifecycle on range fields
On range fields (SingleInputDateRangeField / MultiInputDateRangeField / ... ),
onChange is called if the date you are modifying matches one of the conditions above, regardless of the other date state.
The example below shows the last value received by onChange.
Note how changing the value of the start date section will call onChange even if the end date is empty or partially filled.
Value: 04/17/2022 – null
Lifecycle on pickers: "onClose"
When is "onClose" called?
When the last view is completed
When a selection in the last view is made, onClose will be called only if the closeOnSelect prop is equal to true.
The default value of closeOnSelect depends on the component:
Date Picker and Date Range Picker:
trueon desktop andfalseon mobile variants;Time Picker, Date Time Picker, and Date Time Range Picker:
falseon desktop and mobile variants.Here are a few examples:
<DesktopDatePicker />- Default
viewsprop:['year', 'day'] - Default
closeOnSelectprop:true
Behavior: The picker will close when selecting the day.
- Default
<DesktopDatePicker closeOnSelect={false} />- Default
viewsprop:['year', 'day'] - Explicit
closeOnSelectprop:false
Behavior: The picker will not close when selecting a day. The user will have to click on the OK action to close it.
- Default
<MobileDatePicker />- Default
viewsprop:['year', 'day'] - Default
closeOnSelectprop:false
Behavior: The picker will not close when selecting a day. The user will have to click on the OK action to close it.
- Default
<DesktopDatePicker views={['day', 'month', 'year']} />- Explicit
viewsprop:['day', 'month', 'year'] - Default
closeOnSelectprop:true
Behavior: The picker will close when selecting the year.
- Explicit
<DesktopTimePicker />- Default
viewsprop:['hours', 'minutes'](plus ameridiemview if the locale is in 12-hours format) - Default
closeOnSelectprop:false
Behavior: The picker will not close when selecting the minutes or meridiem (if a 12-hour clock is used).
- Default
When the picker is manually closed
Pressing Escape or clicking outside the picker will close the picker.
When a value is selected using the action bar
Clicking on any built-in button of the action bar will close the picker.
When a shortcut is picked
Clicking on a shortcut will close the picker, except if the changeImportance property has been set to "set" instead of the default value "accept".
You can find more information in the dedicated doc section.
Lifecycle on pickers: "onChange"
Usage
The onChange callback is called whenever the current value changes.
If you don't want to listen to the intermediary steps, consider using the onAccept prop instead.
<DatePicker onChange={(value) => setValue(value)} />
When is "onChange" called?
When the field calls "onChange"
When editing your value through the input(s) of your field, the picker will just re-publish the onChange callback.
Take a look at the dedicated section for more information.
When the user interacts with the view
If the component is controlled (if it has a value prop that isn't undefined),
clicking on a value will call onChange if the value to publish is different from the current value
(for example clicking on the already selected day in the day view will not call onChange).
If the component is not controlled, the behavior is the same, except if no value has ever been published, in which case clicking on the current value will fire onChange
(for example clicking on the already selected day in the day view will call onChange if onChange has never been called before).
Some views can decide not to call onChange for some value modifications.
The most common example is the mobile time views (using the TimeClock component).
The onChange is only fired once when the dragging (touching) of the clock hand ends even though the UI updates on each position change.
When a value is selected using the action bar
If the component is controlled (if it has a value prop that isn't undefined),
clicking on any built-in actions will call onChange if the value to publish is different from the current value.
If the component is not controlled, the behavior is the same, except for the Clear, Today, and OK actions that will call onChange if no value has ever been published, even if the current value equals the value to publish.
When a shortcut is picked
Clicking on a shortcut will call onChange.
You can find more information in the dedicated doc section.
Lifecycle on pickers: "onAccept"
Usage
The onAccept callback lets you get the final value selected by the user without caring about the intermediary steps.
<DatePicker onAccept={(value) => sendValueToServer(value)} />
When is "onAccept" called?
When the last view is completed
When a selection in the last view is made, onAccept will be called only if the closeOnSelect prop is equal to true and the value has been modified since the last time onAccept was called.
The default value of closeOnSelect depends on the component used:
- Date Picker and Date Range Picker:
trueon desktop andfalseon mobile variants; - Time Picker, Date Time Picker, and Date Time Range Picker:
falseon desktop and mobile variants.
Here are a few examples:
<DesktopDatePicker />- Default
viewsprop:['year', 'day'] - Default
closeOnSelectprop:true
Behavior: The picker will call
onAcceptwhen selecting the day.- Default
<DesktopDatePicker closeOnSelect={false} />- Default
viewsprop:['year', 'day'] - Explicit
closeOnSelectprop:false
Behavior: The picker will not call
onAcceptwhen selecting a value.- Default
<DesktopDatePicker views={['day', 'month', 'year']} />- Explicit
viewsprop:['day', 'month', 'year'] - Default
closeOnSelectprop:true
Behavior: The picker will call
onAcceptwhen selecting the year.- Explicit
<DesktopTimePicker />- Default
viewsprop:['hours', 'minutes'](plus ameridiemview if the locale is in 12-hours format) - Default
closeOnSelectprop:false
Behavior: The picker will not call
onAcceptwhen selecting the minutes or meridiem (if a 12-hour clock is used).- Default
When the picker is manually closed
When the user presses Escape or clicks outside the picker, onAccept is called with:
- the current value, if the last view has been completed
- the last accepted value, if the last view has not been completed
When a value is selected using the action bar
If the component is controlled (if it has a value prop that isn't undefined),
clicking on any built-in actions will call onAccept if the value to publish is different from the current value.
If the component is not controlled, the behavior is the same, except for the Clear, Today, and OK actions that will call onAccept if no value has ever been published, even if the current value equals the value to publish.
When a shortcut is picked
Clicking on a shortcut will call onAccept, except if the changeImportance property has been set to "set" instead of "accept".
You can find more information in the dedicated doc section.
Classic scenarios
"DatePicker" on desktop
Controlled "DesktopDatePicker": basic usage
<DesktopDatePicker value={value} onChange={(newValue) => setValue(newValue)} />
Action n°1: Opening the picker
- Opens the picker on the
dayview
Action n°2: Clicking on a day
- Fires
onClose(and closes the picker if theopenprop is not controlled) - Fires
onChangewith the selected day (keeps the time of the previous value) - Fires
onAcceptwith the selected day (keeps the time of the previous value)
Controlled "DesktopDatePicker": picking year, month and day
<DesktopDatePicker
value={value}
onChange={(newValue) => setValue(newValue)}
views={['year', 'month', 'day']}
/>
Action n°1: Opening the picker
- Opens the picker on the
dayview
Action n°2: Switch to the year view on the header
Action n°3: Clicking on a year
- Fires
onChangewith the selected year (keeps the month, date and time of the previous value) - Moves to the
monthview
Action n°4: Clicking on a month
- Fires
onChangewith the selected month (keeps the date and time of the previous value) - Moves to the
dayview
Action n°4: Clicking on a day
- Fires
onClose(and closes the picker if theopenprop is not controlled) - Fires
onChangewith the selected day (keeps the time of the previous value) - Fires
onAcceptwith the selected day (keeps the time of the previous value)
"DatePicker" on mobile
Controlled "MobileDatePicker": basic usage
<MobileDatePicker value={value} onChange={(newValue) => setValue(newValue)} />
Action n°1: Opening the picker
- Opens the picker on the
dayview
Action n°2: Clicking on a day
- Fires
onChangewith the selected day (keeps the time of the previous value)
Action n°3: Clicking on the OK action
- Fires
onClose(and closes the picker if theopenprop is not controlled) - Fires
onAcceptwith the selected day (keeps the time of the previous value)
Only update for valid values
The onChange callback receives a 2nd parameter (context object) containing the validation error associated with the current value.
If you want to update your state only when the value is valid, you can ignore any onChange call with a non-null validationError.
In the example below, onChange will only be called if the date is valid and its year is 2022:
Value: null
Server interaction
If the selected value is used to interact with the server, you might want to avoid sending all the intermediate states.
Especially if the user is setting the date using the keyboard arrow interaction.
In such a case, the recommended UI is to add a button for validating the form.
If for some reason, you need to send the data to the server without having the user pressing a validation button, you can debounce the onChange as follows.
The following demo shows how to extend the Date Field component by adding an onAccept prop, which is a debounced version of onChange.
You can find more information about the onAccept prop in the dedicated doc section.
onChange
onAccept