Material-UI Select コンポーネントのメニューの表示位置を変更する


こんにちは、 Gaji-Labo アシスタントエンジニアの石垣です。

今回は、React 用 UI コンポーネントライブラリである Material-UI の Select コンポーネントでのメニューのポップオーバー位置を変更する方法についてまとめたいと思います。

Material-UI についてはこちらの記事で紹介しておりますので、あわせてお読みください。

Select コンポーネントについて

Material-UI の Select コンポーネントは、表示されている Select をクリック/タップするとメニューがポップオーバーで表示されるという仕様になっています。

このポップオーバーの表示位置は、デフォルトでは Select の左中央を起点に表示されるようになっています。

デフォルトでは Select をクリック/タップすると左中央を起点にメニューが表示される
import React, { ReactElement } from "react";

import { Select, MenuItem } from "@material-ui/core";

interface Props {
  items: { label: string; value: string; disabled: boolean }[];
  value: string;
  onChange: (e: string) => void;
}

export function ExampleSelect({
  items,
  onChange,
  value,
}: Props): ReactElement | null {

  const handleChange = (
    e: React.ChangeEvent<{ name?: string | undefined; value: unknown }>
  ) => {
    onChange(e.target.value as string);
  };

  return (
    <Select
      value={value}
      onChange={handleChange}
      displayEmpty
      variant="outlined"
      MenuProps={{
        getContentAnchorEl: null,
        anchorOrigin: { vertical: "top", horizontal: "left" },
        transformOrigin: { vertical: "top", horizontal: "left" },
      }}
    >
      {items.map((item) => {
        return (
          <MenuItem
            key={item.label}
            value={item.value}
            disabled={item.disabled}
          >
            {item.label}
          </MenuItem>
        );
      })}
    </Select>
  );
}

変更するためにやったこと

これを変更するには、以下のように Select コンポーネントの MenuProps にいくつか props を渡して変更する必要があります。

...

  return (
    <Select
      value={value}
      onChange={handleChange}
      displayEmpty
      variant="outlined"
      MenuProps={{
        getContentAnchorEl: null, // anchorOrigin, transformOrigin が変更可能になるように元々ポップオーバーの基準となっている要素を解除
        anchorOrigin: { vertical: "top", horizontal: "left" }, // ポップオーバーの表示起点
        transformOrigin: { vertical: "top", horizontal: "left" }, // 表示時の transform の起点
      }}
    >
      {items.map((item) => {
        return (
          <MenuItem
            key={item.label}
            value={item.value}
            disabled={item.disabled}
          >
            {item.label}
          </MenuItem>
        );
      })}
    </Select>
  );

...

以上のようにコードを変更すると、ポップオーバーの起点位置が左上に変更されます。

anchorOrigin に渡す値を変更することで、左上以外に設定することも可能です。

メニューの表示位置が左上に変更された

Props の渡し方について

なぜこのような形で props を渡す必要があるかというと、 セレクトをクリック/タップしてポップオーバーするメニューは、 Select が内包している Menu という Select とはまた別の Material-UI コンポーネントで実装されているためです。

ポップオーバーするメニューの表示位置は、 Select からは変更することが出来ず、 Menu コンポーネントに props を渡して変更することになります。

SelectMenuProps という props を持っているため、それを介して内包されている Menu に props を渡すことができます。

Material-UI にはこのように複数のコンポーネントが組み合わさって作られているコンポーネントが他にも多く存在しており、そういったコンポーネントで内包されているコンポーネントを操作する必要がある時は、基本的に上位のコンポーネントが持つ FooProps を介して子に props を渡すことになります。

まとめ

今回は、React 用 UI コンポーネントライブラリである Material-UI の Select コンポーネントでのメニューのポップオーバー位置を変更する方法についてまとめました。

Material-UI を使っている方の参考にしていただけたらと思います。

開発のお悩み、フロントエンドから解決しませんか?

あなたのチームのお悩みはなんですか?

「バックエンドエンジニアにフロントエンドまで任せてしまっている」
「デザイナーに主業務以外も任せてしまっている」
「すべての手が足りず細かいことまで手が回らない」

役割や領域を適切に捉えてカバーし、チーム全体の生産性と品質をアップするお手伝いをします。
フロントエンド開発に関わるお困りごとがあれば、まずは一度お気軽に Gaji-Labo にお声がけください。

オンラインでのヒアリングとフルリモートでのプロセス支援に対応しています。

リモートワーク対応のパートナーをお探しの場合もぜひ弊社にお問い合わせください!

お悩み相談はこちらから!

投稿者 Ishigaki Shotaro

未経験から Gaji-Labo に入社。現在は React/TypeScript/Next.js の案件で MUI を使ったコンポーネント組み込みを担当。プロジェクトチームのリードとして共に組み込み作業をしているメンバーの進行管理も行っています。休日はだいたい家で音楽を聴いており、たまにライブに出かけています。