Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

877
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda