Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pickers] Manage input value without using the focus #4486

Merged
merged 10 commits into from
Jun 1, 2022

Conversation

alexfauquette
Copy link
Member

@alexfauquette alexfauquette commented Apr 13, 2022

Related issues (are they fixed?)

The original problem

The useMaskedInput track the input focus state for the following reason (a comment can be found here https://github.com/mui/material-ui/pull/25972/files )

If a user enters '01/01/1' date adapters consider it as the 1st of January 0001. Then onChange is called with new Date(1,1,1). Since we encourage developers to do the following, the TextField value will be set to '01/01/0001', leading to really difficult editing behavior (impossible to delete a single character in the year).

<DatePicker
	value={value}
	onChange={(newValue) => setValue(newValue)}
/>

Why it is not a good solution

The assumption is

If the input has focus, we should let what is typed as it is

But this behavior lets the components have two different renderings for the same props, leading to bug #4479 in which the dev wants to implement the following feature: "When I press Del it erases the date".

The straightforward solution is to use onKeyDow and set the value to null if Del is pressed. But if the input has the focus the modification will be ignored by the component, and so the previous value will still be visible.

Proposed solution

In this PR I remove the focus management since it leads to inconsistencies between the controlled value and the displayed one

Add acceptInconsistentFormat prop with the default set to false. an input is considered as an inconsistentFormat if parsing and formatting is not the identity function. For example with inputFormat dd/MM/YYYY, it makes the following transformations

'10/12/1' -> Date(1, 11, 10) -> '10/12/0001' // inconsistent
'10/12/1994' -> Date(1994, 11, 10) -> '10/12/1994' // consistent

So with acceptInconsistentFormat=false the first input will not call onChange

Why it does not work

We need to be able to desync the displayed text from the date input. Because we need to be able to type partial date which corresponds to invalid date

When filling the date we can wait to reach a complete one with the acceptInconsistentFormat=true
But if the user entered a date (for example '01/01/1998') and deletes a character, it will now be '01/01/199' which should call onChange to say that the date is now invalid

New solution

I observed that currently the onChange is called even with date such as 01/01/19 which is not formatted because the component has the focus. Now it will still call onChange with date 01/01/19 but not format the new date, because the current text already corresponds to the new date

@mui-bot
Copy link

mui-bot commented Apr 13, 2022

These are the results for the performance tests:

Test case Unit Min Max Median Mean σ
Filter 100k rows ms 277.7 517.4 403.1 395.08 78.977
Sort 100k rows ms 521.9 1,004.4 704.2 789.52 166.413
Select 100k rows ms 126.9 180.2 141.9 150.52 21.524
Deselect 100k rows ms 117.2 238 140.5 154.36 43.221

Generated by 🚫 dangerJS against fe42709

Unverified

This commit is not signed, but one or more authors requires that any commit attributed to them is signed.

Unverified

This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
@github-actions github-actions bot added the PR: out-of-date The pull request has merge conflicts and can't be merged label Apr 29, 2022
@github-actions
Copy link

This pull request has conflicts, please resolve those before we can evaluate the pull request.

@alexfauquette alexfauquette changed the title PR to test if removing the check on input focus solves the issue [WIP] Manage input value without using the focus May 12, 2022

Unverified

This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
@github-actions github-actions bot removed the PR: out-of-date The pull request has merge conflicts and can't be merged label May 13, 2022

Unverified

This commit is not signed, but one or more authors requires that any commit attributed to them is signed.

Unverified

This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
@alexfauquette alexfauquette changed the title [WIP] Manage input value without using the focus Manage input value without using the focus May 16, 2022
@alexfauquette alexfauquette marked this pull request as ready for review May 16, 2022 18:41
@alexfauquette
Copy link
Member Author

It appears that adding acceptInconsistentFormat prop is not necessary

To handle case when user type 01/01/1 without setting the text to 01/01/0001 The idea is to consider that users do

onChange={(x)=>{
	setValue(x); 
	if(validate(x)){
		onValidate(x)
	}
}

As long as they do not modify the date from the onChange we do not format it

Unverified

This commit is not signed, but one or more authors requires that any commit attributed to them is signed.

Unverified

This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
@flaviendelangle flaviendelangle changed the title Manage input value without using the focus [pickers]Manage input value without using the focus Jun 1, 2022
@flaviendelangle flaviendelangle changed the title [pickers]Manage input value without using the focus [pickers] Manage input value without using the focus Jun 1, 2022

Unverified

This commit is not signed, but one or more authors requires that any commit attributed to them is signed.

Unverified

This commit is not signed, but one or more authors requires that any commit attributed to them is signed.

Unverified

This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
Copy link
Member

@flaviendelangle flaviendelangle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The behavior looks good to me

It's probably worth reproducing by hand each issue linked in the PR description to see if the behavior is now good.

And link those issues as fixed to have GitHub close them automatically

@alexfauquette
Copy link
Member Author

I added the "Fix" before each issue. If someone else also wants to experiment the bugs with this PR fix, I linked a codesandbox for each issue.

The codesandbox is the initial minimal reproduction of the issue, with the package generated by this PR

@alexfauquette alexfauquette merged commit f8dd5d2 into mui:master Jun 1, 2022
@alexfauquette alexfauquette deleted the test-noFocus branch June 1, 2022 13:50
joserodolfofreitas pushed a commit to joserodolfofreitas/mui-x that referenced this pull request Jun 13, 2022

Unverified

This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
alexfauquette added a commit to alexfauquette/mui-x that referenced this pull request Aug 26, 2022

Unverified

This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
@Lukortech
Copy link

Lukortech commented Oct 20, 2022

DatePicker in @mui/x-date-pickers does not update value onChange, still.
More context in this issue: #4479 (comment)

Seems like it was "fixed" but in version 5.0.4 which I use it's still prevalent

@alexfauquette
Copy link
Member Author

Hi @Lukortech, could you open an issue with a code sandbox demo of what you want to achieve and what is the unexpected behavior? Otherwise we will not be able to keep track of your bug

@zannager zannager added the component: pickers This is the name of the generic UI component, not the React module! label Jan 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: pickers This is the name of the generic UI component, not the React module!
Projects
None yet
5 participants