Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

885
Visualizações
Material UI DatePicker custom renderInput

I recently started using material-ui in my React + TypeScript project. The code below was written based on the sample code on the official website.

import AdapterDateFns from '@mui/lab/AdapterDateFns';
import DatePicker from '@mui/lab/DatePicker';
import LocalizationProvider from '@mui/lab/LocalizationProvider';
import TextField from '@mui/material/TextField';
import React, { useState } from 'react';

const SampleDatePickerOriginal = () => {
  const [date, setDate] = useState<Date>(new Date());

  const onChangeHandler = (_date: Date | null, keyboardInputValue?: string) => {
    if (_date) {
      setDate(_date);
    }
  };
  return (
    <LocalizationProvider dateAdapter={AdapterDateFns}>
      <DatePicker
        onChange={onChangeHandler}
        value={date}
        renderInput={(params) => <TextField {...params} />}
      />
    </LocalizationProvider>
  );
};

export default SampleDatePickerOriginal;

I wanted to use input element instead of TextField in this code. So I referred to material-ui's issue (https://github.com/mui/material-ui-pickers/issues/1751) and wrote the code below.

import AdapterDateFns from '@mui/lab/AdapterDateFns';
import DatePicker from '@mui/lab/DatePicker';
import LocalizationProvider from '@mui/lab/LocalizationProvider';
import React, { useState } from 'react';

const SampleDatePickerCustom = () => {
  const [date, setDate] = useState<Date>(new Date());
  const [isOpen, setIsOpen] = useState<boolean>(false);

  const onChangeHandler = (_date: Date | null, keyboardInputValue?: string) => {
    if(_date){
      setDate(_date);
    }
  };

  return (
    <LocalizationProvider dateAdapter={AdapterDateFns}>
      <DatePicker 
        onChange={onChangeHandler}
        onClose={() => {setIsOpen(false);}}
        open={isOpen}
        value={date} 
        renderInput={({
          ref,
          inputProps,
          disabled,
          onChange,
          value,
          ...other
        }) => (
          <div ref={ref}>
            <input
              style={{ display: 'none' }}
              value={date.toISOString()}
              onChange={onChange}
              disabled={disabled}
              {...inputProps}
            />
            <button onClick={() => {setIsOpen(!isOpen);}}>
              OPEN
            </button>
          </div>)} />
    </LocalizationProvider>
  );
};

export default SampleDatePickerCustom;

This code works fine, but the calendar that opens is in the upper left corner. How can I make it appear just below the button like when I use TextField?

about 4 years ago · Juan Pablo Isaza
2 Respostas
Responde à pergunta

0

I was stuck on the same problem here today and luckily got it working for me now.

The idea is that you have to pass an anchor element to the Material UI Popper component, which is basically the wrapper for your Datepicker Popup. That means you have to create a ref object for your custom input and pass that to the popper object as anchorEl. If you check the MaterialUI X documentation for the Datepicker API, you can see it under the Props section as PropperProps.

Your code then would look something like this:

import React, { useState, useRef } from 'react';

const SampleDatePickerCustom = () => {
  const [date, setDate] = useState<Date>(new Date());
  const [isOpen, setIsOpen] = useState<boolean>(false);
  const customInputRef = useRef();

  const onChangeHandler = (_date: Date | null, keyboardInputValue?: string) => {
    if(_date){
      setDate(_date);
    }
  };

  return (
    <LocalizationProvider dateAdapter={AdapterDateFns}>
      <DatePicker 
        onChange={onChangeHandler}
        onClose={() => {setIsOpen(false);}}
        open={isOpen}
        value={date} 
        PopperProps={{ anchorEl: customInputRef.current }}
        renderInput={({
          ref,
          inputProps,
          disabled,
          onChange,
          value,
          ...other
        }) => (
          <div ref={ref}>
            <input
              style={{ display: 'none' }}
              value={date.toISOString()}
              onChange={onChange}
              disabled={disabled}
              ref={customInputRef}
              {...inputProps}
            />
            <button onClick={() => {setIsOpen(!isOpen);}}>
              OPEN
            </button>
          </div>)} />
    </LocalizationProvider>
  );
};

The only things that I added are the customInputRef object, which is assigned as a ref to your input and the PropperProps object on your Datepicker, which only has one property, the customInputRef.current element. That should make the Popper be anchored at the provided custom input element. I didn't type the additions, since I'm not the best at TS, but I hope it's enough to understand how it works :)

about 4 years ago · Juan Pablo Isaza Relatório

0

I was able to work around it by using TextField but hiding it with styles... <TextField style={{ opacity: 0, width: 0, height: 0 }} {...params} />

<LocalizationProvider dateAdapter={AdapterDateFns}>
   <DatePicker
    open={calendarOpen}
    onClose={() => setCalendarOpen(false)}
    value={date}
    onChange={(newValue) => setDate(newValue)}
    renderInput={(params) => (
      <div>
      {/* HACK: this next line was needed to get the calendar to render in the right position */}
        <TextField style={{ opacity: 0, width: 0, height: 0 }} {...params} /> 
        <Button
          className="p-1"
          variant="outlined"
          onClick={() => setCalendarOpen((calendarOpen) => !calendarOpen)}>
          <CalendarIcon />
        </Button>
      </div>
    )}
  />
</LocalizationProvider>
about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda