Open MartinJaskullaTS opened 1 month ago
I just noticed that the same issue exists when selecting a custom date range e.g. clicking on today's date in the calendar, which makes a "Today" shortcut also unusable, which would add it as a query param to allow bookmarking/sharing.
This shows a workaround I tried and another behaviour I don't understand: https://codesandbox.io/p/sandbox/dx8gs6
Why does the DateRangePicker become empty after setting value
to the current date range?
function B() {
const [value, setValue] = useState<[Dayjs | null, Dayjs | null]>([
dayjs("01-01-2020"),
dayjs("01-01-2020"),
]);
return (
<>
<p>onAccept called, but input becomes empty, then broken:</p>
<DateRangePicker
slotProps={{
shortcuts: {
items: [
{
label: "01.01.2020",
getValue: () => {
// Fake date that differs from current value to trigger onAccept
return [null, null];
},
},
],
},
}}
value={value}
onAccept={(v, context) => {
alert("onAccept called");
// Set the real shortcut value. However, DateRangePicker breaks, because the same dates are set.
setValue([dayjs("01-01-2020"), dayjs("01-01-2020")]);
}}
/>
</>
);
}
I guess that DateRangePicker has an internal check that compares the new value
prop to the previous one and then something unexpected happens. But why have such a check? If I pass in a value
, I expect it to be shown.
Found a better workaround, which I still don't like.
shortcuts: {
onClick: (e) => console.log(e.target),
items: [
{
id: "1",
label: "01.01.2020",
getValue: () => {
return [dayjs("01-01-2020"), dayjs("01-01-2020")];
},
},
],
},
e.target
will be either ul
, li
, <div id="1">
or <span>01.01.2020</span>
depending on where you click on the shortcut. Based on the id
, I can find the clicked shortcut.
Sidenote:
Maybe it would be better for <div id="1">
to use a data attribute: <div data-shortcut-id="1">
instead to prevent multiple elements with the same id
.
I get what you are trying to achieve and I do think that both approaches actually make sense. We could introduce a prop to allow for a commit even when the values did not change. From https://github.com/mui/mui-x/blob/0f0a7ec0ea4ffcd09e1290919ae3a1b714d74746/packages/x-date-pickers/src/internals/hooks/usePicker/usePickerValue.ts#L261
- hasChanged: (comparison) => !valueManager.areValuesEqual(utils, action.value, comparison),
+ hasChanged: (comparison) => rootProps.commitEqualValues || !valueManager.areValuesEqual(utils, action.value, comparison),
@LukasTy WDYT?
I get what you are trying to achieve and I do think that both approaches actually make sense. We could introduce a prop to allow for a commit even when the values did not change. From
- hasChanged: (comparison) => !valueManager.areValuesEqual(utils, action.value, comparison), + hasChanged: (comparison) => rootProps.commitEqualValues || !valueManager.areValuesEqual(utils, action.value, comparison),
@LukasTy WDYT?
On second though the name might be misleading and adding it in the hasChanged
is semantically incorrect. Better solution:
- const shouldCommit = shouldCommitValue(updaterParams);
+ const shouldCommit = rootProps.commitEqualValues || shouldCommitValue(updaterParams);
I just noticed that the same issue exists when selecting a custom date range e.g. clicking on today's date in the calendar, which makes a "Today" shortcut also unusable, which would add it as a query param to allow bookmarking/sharing.
[...]
I guess that DateRangePicker has an internal check that compares the new
value
prop to the previous one and then something unexpected happens. But why have such a check? If I pass in avalue
, I expect it to be shown.
In this regard, you seem to be bumping into this issue: https://github.com/mui/mui-x/issues/10424 🙈
In regards to onAccept
being called after every change, regardless of the value change:
I would like us to avoid adding props here to control the behavior. 🙈
IMHO, either we remove the logic comparing the current value with the last published one and call onAccept
every time or add the option to control this behavior externally (hook or some other means).
@flaviendelangle, you have worked quite a bit on the lifecycle. WDYT, would ditching the comparison and calling onAccept
more often be feasible? Or are there any known roadblocks? 🤔
If you don't change anything about onAccept
and instead allow passing every prop of Chip
to each shortcut, you solve other problems as well e.g. shortcuts with long text having text-overflow: ellipsis
, but no way of showing a title
on hover.
So maybe:
<DateRangePicker
slotProps={{
shortcuts: {
items: [
{
getValue: () => {...},
label: "Very loooooooooooooooooooooooooong label",
// Allow all properties of Chip (each shortcut is a Chip)
onClick: () => {} // Fixes the problem of this issue
title: "Very loooooooooooooooooooooooooong label" // Fixes the text overflow issue
},
],
},
}}
/>
Or
<DateRangePicker
slotProps={{
shortcuts: {
items: [
{
getValue: () => {...},
slotProps: {
label: "Very loooooooooooooooooooooooooong label",
onClick: () => {}
title: "Very loooooooooooooooooooooooooong label"
}
},
],
},
}}
/>
You can see the text overflow issue also in the screenshot here: "Same period last year (...".
Just to add title
I need to provide my own custom shortcuts
slot
.
The DateRangePicker's
onAccept
callback is not called if the same date range is selected. This is by design.However, this design does not allow some use cases.
I am using
shortcuts
, which also triggeronAccept
when clicked. There can be semantically different shortcuts that result in the same date range in certain situations. These are unusable at the moment.Let's say I have 2 shortcuts:
If its 2024, both would set the range 24.12.2023 - 24.12.2023. If its 2025, one would set 24.12.2023 - 24.12.2023, the other 24.12.2024 - 24.12.2024.
If a shortcut is clicked, I add it as a query parameter to the URL e.g. &preset=christmas_23 or &preset=christmas_last_year. This way users can share the link or bookmark it.
Let's say its 2024 and a user clicks "Christmas 2023". Now they want to change to "Christmas last year", bookmark it and open the bookmark in 2025, 2026 etc. They can't, because
onAccept
is not called. There is also no convenient way for me to get notified about the click, because each individual shortcut does not have anonClick
property.I think
onAccept
should always be called. The feature that MUI is checking if the dates did not change to not callonAccept
does not provide a lot of value. Checking this myself in myonAccept
callback is trivial. If always callingonAccept
is not possible, then at least there should be a convenient to know, which shortcut was clicked.The Christmas example is somewhat contrived. My actual use case is a date range comparison feature in an analytics dashboard, where I have two date range inputs, which both have shortcuts. Some shortcuts of the second comparison range can in certain scenarios have same date range. This depends on what date range was selected in the first base date range.
Combination 1: Input 1 shortcut: Last 365 days -> 26.09.23 - 24.09.23 Input 2 shortcut: Previous year (same period) -> 26.09.23 - 25.09.23
Combination 2: Input 1 shortcut: Last 365 days -> 26.09.23 - 24.09.23 Input 2 shortcut: Preceding period -> 26.09.23 - 25.09.23
"Previous year (same period)" is currently selected in input 2. The user is not able to click on "Preceding period" via the shortcut (red rectangle). They might want to switch the comparison "mode" (the shortcut) first and then change input 1 to "Last 7 days". If they do that, the two shortcuts ("Previous year...", "Preceding period", ) would result in different date ranges.
Related issues: https://github.com/mui/mui-x/issues/8129#issuecomment-1473811868 https://github.com/mui/mui-x/issues/4898#issuecomment-1127482474
Your environment
`npx @mui/envinfo`
``` System: OS: macOS 14.6.1 Binaries: Node: 16.20.2 - ~/.nvm/versions/node/v16.20.2/bin/node npm: 8.19.4 - ~/.nvm/versions/node/v16.20.2/bin/npm pnpm: Not Found Browsers: Chrome: 128.0.6613.120 Edge: Not Found Safari: 17.6 npmPackages: @emotion/react: 11.13.3 @emotion/styled: 11.13.0 @mui/core-downloads-tracker: 6.1.1 @mui/icons-material: 6.1.1 @mui/material: 6.1.1 @mui/private-theming: 6.1.1 @mui/styled-engine: 6.1.1 @mui/system: 6.1.1 @mui/types: 7.2.17 @mui/utils: 6.1.1 @mui/x-date-pickers: 7.18.0 @mui/x-date-pickers-pro: 7.18.0 @mui/x-internals: 7.18.0 @mui/x-license: 7.18.0 @types/react: 18.3.3 => 18.3.3 react: 18.3.1 react-dom: 18.3.1 typescript: 5.5.3 => 5.5.3 ```Search keywords: daterangepicker shortcuts onaccept Order ID: 96659