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] DatePicker: adding a inputAdornment when a condition is met #9285

Closed
2 tasks done
TheRealCuran opened this issue Jun 9, 2023 · 14 comments
Closed
2 tasks done
Assignees
Labels
component: pickers This is the name of the generic UI component, not the React module! docs Improvements or additions to the documentation support: commercial Support request from paid users

Comments

@TheRealCuran
Copy link

TheRealCuran commented Jun 9, 2023

Order ID or Support key 💳 (optional)

61706

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version

The problem in depth 🔍

We have a search interface where people can pick dates to refine the search. When a date is selected, we add the <Clear /> SVG icon and allow users to easily reset the filter. With MUI-X 5.x this worked with the following code:

renderInput={({ InputProps, ...params }) => (
  <TextField
    {...params}
    InputProps={{
      ...InputProps,
      endAdornment: (
        <React.Fragment>
          {this.state.date && (
            <IconButton onClick={(e) => {
              e.stopPropagation();
              setDate(null);
            }}>
              <Clear />
            </IconButton>
          )}
          {InputProps?.endAdornment}
        </React.Fragment>
      ),
    }}
  />
)}

Now, with MUI-X 6 renderInput is gone and one should use slotProps/slots. I tried rewriting this with slotProps but are failing to even manage to get the <Clear /> icon to show (not to mention in addition to the default Icon for opening the picker). The only thing I can manage reliably is to move the postion around – it looks to me like my children parameter gets overwritten. Similar results with slots and trying to basically use the old code on the TextField in there.

For reference the code with slotProps (which should at least replace icon, but doesn't do even that):

slotProps={{
  inputAdornment: this.state.date ? {
    position: 'end',
    children: (
      <IconButton onClick={(e) => {
        e.stopPropagation();
        setDate(null);
      }}>
        <Clear />
      </IconButton>
    ),
  } : undefined,
}}

I am pretty sure I have the correct slot here, since when I change position: 'end' to position: 'start' I can see it moving to the front on selecting a date. But still, the <Clear /> icon stays invisible.

And I have not found anything in the documentation that might help me. Can somebody please point me in the right direction so I can finish the upgrade to MUI-X 6.x? Bonus points if we can show the clear icon in addition to the picker icon again. Thanks.

P.S.: This might also be a bug and may or may not be related to #8322.

Your environment 🌎

`npx @mui/envinfo`
    System:
    OS: Linux 6.3 Debian GNU/Linux 12 (bookworm) 12 (bookworm)
  Binaries:
    Node: 18.13.0 - /usr/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 9.2.0 - /usr/bin/npm
  npmPackages:
    @emotion/react: ^11.10.4 => 11.11.1 
    @emotion/styled: ^11.10.4 => 11.11.0 
    @mui/base:  5.0.0-beta.4 
    @mui/core-downloads-tracker:  5.13.4 
    @mui/icons-material: ^5.10.3 => 5.11.16 
    @mui/material: ^5.10.3 => 5.13.4 
    @mui/private-theming:  5.13.1 
    @mui/styled-engine:  5.13.2 
    @mui/system: ^5.10.3 => 5.13.2 
    @mui/types:  7.2.4 
    @mui/utils:  5.13.1 
    @mui/x-date-pickers:  6.7.0 
    @mui/x-date-pickers-pro: ^6.7.0 => 6.7.0 
    @mui/x-license-pro: ^6.6.0 => 6.6.0 
    @types/react:  18.2.9 
    react: ^18.0.0 => 18.2.0 
    react-dom: ^18.0.0 => 18.2.0
The problem surfaces in a Electron 25 environment.
@TheRealCuran TheRealCuran added status: waiting for maintainer These issues haven't been looked at yet by a maintainer support: commercial Support request from paid users labels Jun 9, 2023
@LukasTy
Copy link
Member

LukasTy commented Jun 9, 2023

We are currently working on providing an out-of-the-box solution for clearing the input. 😉
As for ideas and inspiration for a solution on your end, have you checked the following demo using the adornment merging strategy? 🤔

@LukasTy LukasTy added component: pickers This is the name of the generic UI component, not the React module! and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Jun 9, 2023
@LukasTy LukasTy changed the title [question] DatePicker: adding a inputAdornment when a condition is met [pickers] DatePicker: adding a inputAdornment when a condition is met Jun 9, 2023
@TheRealCuran
Copy link
Author

Thanks for answering so quickly!

The out-of-the-box solution sounds awesome!

As for the merging strategy: no, I haven't seen that. Will check it out in detail on Monday. But right away I am wondering how to reach the renderInput on TextField through the slots. I have tried the following before:

slots={{
  textField: {
    renderInput: ({ InputProps, ...params }) => (
      <TextField
        {...params}
        InputProps={{
          ...InputProps,
          endAdornment: (
            <React.Fragment>
              {this.state.date && (<IconButton onClick={(e) => {
                e.stopPropagation();
                setDate(null);
              }}>
                <Clear />
              </IconButton>
            )}
            {InputProps?.endAdornment}
          </React.Fragment>
        ),
      }}
    />)
  }
}}

But that cause render() in DatePicker to be unhappy.

@TheRealCuran
Copy link
Author

TheRealCuran commented Jun 13, 2023

OK, the solution is something like this:

<DatePicker
    format="MM/yyyy"
    mask="__/____"
    views={['year', 'month']}
    slots={{
        textField: params => (
            <TextField
                {...params}
                InputProps={{
                    ...params.InputProps,
                    endAdornment: this.mergeAdornments(
                        'toDate',
                        this.endAdornment(
                            this.props.myDate.visible,
                            (e) => { e.stopPropagation(); this.props.myDate.cb(null); },
                        ),
                        params.InputProps?.endAdornment ?? null,
                    ),
                }}
            />
        ),
    }}
    aria-label="Select Date"
    value={this.dateFromEpoch(this.state.myDate)}
/>

Though this does break the positioning of the popover of the DatePicker. The first part (year) works, but the month jumps all over the place.

@LukasTy
Copy link
Member

LukasTy commented Jun 13, 2023

Hello @TheRealCuran, thank you for providing a solution on your own.
I've tinkered around a bit and was able to come up with the following demo.

Your version was missing the ...params.InputProps spreading to avoid the ref issue.

Don't forget to always provide slot item as a separate component instead of a direct render function, which would be re-rendered each time the root component is rendered.

@TheRealCuran
Copy link
Author

Thanks for the example!

Actually I had the spread of ...params.InputProps in there (and it is in my comment above), but on the first C&P I accidentality deleted it when indenting for GitHub.

The note about providing a distinct component was the missing part, now the anchoring of the popover works again!

This ticket can be closed as far as I am concerned, though it would be nice if the documentation could be expanded a bit.

@LukasTy
Copy link
Member

LukasTy commented Jun 13, 2023

This ticket can be closed as far as I am concerned, though it would be nice if the documentation could be expanded a bit.

Which particular documentation do you feel needs more information or examples?

@TheRealCuran
Copy link
Author

IMHO this section in the documentation (it is what you find, when you look for slots and slotProps, sadly not the top result in the search for either) could really benefit from a couple of examples on how to use the slots and slotProps, especially in conjunction with each other.

@LukasTy LukasTy added the docs Improvements or additions to the documentation label Sep 19, 2023
@LukasTy
Copy link
Member

LukasTy commented Sep 19, 2023

We've decided to improve the documentation on slots and slotProps on our end because the picker components are sometimes quite deeply nested and the general Mui Base documentation on this topic might not be enough.

The proposed solution was to:

@TheRealCuran
Copy link
Author

That sounds great!

I don't really see the mention (only one hit for slotProps) in https://mui.com/x/react-date-pickers/base-concepts/ when I search the page.

https://mui.com/x/react-date-pickers/custom-components/ however goes into more detail and would probably have been enough for me.

Once you feel all the updates to the docs have been merged, you can feel free to close this issue.

Thanks again, for taking care of this!

@flaviendelangle
Copy link
Member

Closed by #10421

@LukasTy LukasTy closed this as completed Mar 4, 2024
Copy link

github-actions bot commented Mar 4, 2024

⚠️ This issue has been closed.
If you have a similar problem, please open a new issue and provide details about your specific problem.
If you can provide additional information related to this topic that could help future readers, please feel free to leave a comment.

How did we do @TheRealCuran?
Your experience with our support team matters to us. If you have a moment, please share your thoughts through our brief survey.

@MishaAkram
Copy link

MishaAkram commented Sep 9, 2024

Hello @TheRealCuran, thank you for providing a solution on your own. I've tinkered around a bit and was able to come up with the following demo.

Your version was missing the ...params.InputProps spreading to avoid the ref issue.

Don't forget to always provide slot item as a separate component instead of a direct render function, which would be re-rendered each time the root component is rendered.

I was having issue that the each time the component render it would loose its state and ref, converting the textfield render function to a separate component helped. thanks!

But there's still one problem the picker value doesn't change on first input, any reason why?

@LukasTy
Copy link
Member

LukasTy commented Sep 10, 2024

I was having issue that the each time the component render it would loose its state and ref, converting the textfield render function to a separate component helped. thanks!

But there's still one problem the picker value doesn't change on first input, any reason why?

Could you clarify what you mean by value doesn't change? 🤔
Maybe you are referring to the component/value lifecycle and the fact that we fire on change only when the value changes (from null to Invalid date or a valid date)?

@MishaAkram
Copy link

I was having issue that the each time the component render it would loose its state and ref, converting the textfield render function to a separate component helped. thanks!
But there's still one problem the picker value doesn't change on first input, any reason why?

Could you clarify what you mean by value doesn't change? 🤔 Maybe you are referring to the component/value lifecycle and the fact that we fire on change only when the value changes (from null to Invalid date or a valid date)?

I realized that my initial value was a string, which made it invalid. I converted it to a date instance, which resolved the issue.

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! docs Improvements or additions to the documentation support: commercial Support request from paid users
Projects
None yet
Development

No branches or pull requests

5 participants