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

アシスタントエンジニアとしてHTML/CSS/JavaScriptの実装やRailsの組み込み、スタイルガイドの構築などを担当しています。 業務の中でさまざまな学びを吸収しながら、文書構造やアクセシビリティに目を向けたマークアップの学習やJavaScriptの学習などを行っています。チームに貢献できるエンジニアとなるために日々奮闘中です。