0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

MUIのdatePickerで削除ボタンを実装する

Last updated at Posted at 2023-10-12

対象読者

  • React、Next.jsを1ヶ月程度触ったことがある
  • MUIを使ったアプリを作成している

MUIって便利ですよね

UI/UXのコンポーネントがまとまっているMUIはとても便利です。
自分でコンポーネントを作る手間が大幅に省けます。
意外とカスタマイズも結構できるので、デザインにも幅を持たせることができます。(センス次第で...)

datePickerってかゆところに手が届かないんですよね

カレンダー入力はめっちゃありがたいんですけど、入力内容を削除する時が結構めんどくさいんですよね。
1回で全部削除することができないので、YYYY削除して、MM削除して、DD削除してみたいなことしなきゃいけなくて..。
しかも自分は後続で日付フォーマットの変換を入れてたから、一部分を削除するとエラーが出てしまったりして悩んでました。

うーん....
じゃあdatepickerをカスタマイズしちゃおう!

datePickerの基本形の導入方法

基本的な実装は色々な方が行なっているので、そちらを参考にしてください。
自分はMUIの公式のドキュメントを参考に実装しました。
結局公式ドキュメントが一番頼りになります。
(自分のコードだけを参考にするとライブラリでエラーになると思うので、公式を参考に導入するようにしてください)

早速完成形

スクリーンショット 2023-10-01 23.10.21.png

やや!なんかXボタンがありますね。
押してみると...
スクリーンショット 2023-10-01 23.11.58.png
入力内容が全て消えました!便利!!

コード紹介

import React, { useState } from "react";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import { DatePicker } from "@mui/x-date-pickers/DatePicker";
import { IconButton } from "@mui/material";
import ClearIcon from "@mui/icons-material/Clear";
import CalendarTodayIcon from "@mui/icons-material/CalendarToday";

export default function CommonDatePicker(props: any) {
  //カレンダーの表示を制御する
  const [open, setOpen] = useState(false);

  //datePickerの入力値を受け取る
  const [value, setValue] = useState(null);

  //バツボタンを押したらvalueをnullにする
  const onClear = () => {
    setValue(null);
  };

  return (
    <LocalizationProvider dateAdapter={AdapterDayjs}>
      <DatePicker
        format="YYYY/MM/DD"
        sx={{ width: "240px" }}
        open={open}
        onOpen={() => setOpen(true)}
        onClose={() => setOpen(false)}
        value={value}
        onChange={(newValue) => setValue(newValue)}
        slotProps={{
          textField: {
            InputProps: {
              endAdornment: (
                <>
                  {value && (
                    <IconButton onClick={onClear}>
                      <ClearIcon />
                    </IconButton>
                  )}
                  <IconButton onClick={() => setOpen(true)}>
                    <CalendarTodayIcon />
                  </IconButton>
                </>
              ),
            },
          },
        }}
      />
    </LocalizationProvider>
  );
}

だいぶ複雑になってしまいましたね。

このslorPropsがキモです

slotProps={{
  textField: {
    InputProps: {
      endAdornment: (
        <>
          {value && (
            <IconButton onClick={onClear}>
              <ClearIcon />
            </IconButton>
          )}
          <IconButton onClick={() => setOpen(true)}>
            <CalendarTodayIcon />
          </IconButton>
        </>
      ),
    },
  },
}}

slotPropsとはdatePickerの内部コンポーネントにプロパティを渡すプロパティです。
slotPropsの中で、textFieldのendAdornmentのプロパティを渡すことでバツボタンとカレンダーを表示しています。
(ここの書き方は自分も深く理解していないです)

ここまで辿り着いても問題がありまして、
バツボタンを導入するためにendAdornmentを指定したらカレンダーが消えてしまうんです...
カレンダー入力のためのアイコンとバツボタンを2つともendAdornmentで指定する必要があります。
カレンダーの表示/非表示を制御も自分で入れないといけません。

open={open}
onOpen={() => setOpen(true)}
onClose={() => setOpen(false)}

また、バツボタンは日付が入力されている場合のみ表示したいので、そのような条件も入れています。

<>
  {value && (....
....
</>

valueはuseStateで管理しています。

//datePickerの入力値を受け取る
const [value, setValue] = useState(null);

いかがでしたでしょうか

初めて技術記事を挙げてみました。
色々と調べてここに辿り着いたので、誰かの助けになればと思い書いてみました!
もしこの記事で誰かの時短になればすごく嬉しいです!

間違っている点や、改善できる点などありましたらぜひ教えてください〜!

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?