[備忘録] Streamlitで作る便利な入力補完機能！

## はじめに

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/f6e62721-4d90-4215-baa8-5bf6117b75ed.png)
Webアプリを作る際に、ユーザーの入力をサポートする「入力補完」機能は非常に便利です。
今回はPythonのStreamlitを使って、シンプルながら実用的な入力補完機能の実装方法を紹介します。この記事は自分の学習内容の備忘録として書いていますが、同じような機能を実装したい方の参考になれば幸いです。

## 実装するもの

今回実装するのは次の機能を持つ簡単なフォームです：

1. ドロップダウンリストから選択できる入力補完
2. リストにない項目を自由に入力できるカスタム入力欄
3. 入力内容の確認と検証

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/648bcaaf-8ca9-42cc-b12e-19ec95195fe5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/bd2b754b-fd99-456f-aa37-895e3756f336.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/cead1850-1731-41d4-9fbe-2cec87e5cbe1.png)


## コード全体

まずは完成したコード全体を見てみましょう：

```python
import streamlit as st

# 入力候補（本来はDBから取得してもOK）
suggestions = ["Apple", "Banana", "Blueberry", "Cherry", "Grape", "Mango", "Orange", "Peach"]

st.set_page_config(page_title="入力補完サンプル", layout="centered")
st.title("🍓 入力補完付きフォーム")

# 補完候補から選択
selected = st.selectbox("フルーツを選ぶか入力してね", [""] + suggestions)

# 新しい値を入力したい場合
if selected == "":
    custom_value = st.text_input("新しいフルーツ名を入力")
else:
    custom_value = selected

# 入力確認
if st.button("✅ 決定"):
    if custom_value:
        st.success(f"選ばれたフルーツ：**{custom_value}**")
    else:
        st.warning("何か入力してください！")
```

たった20行程度のコードで、実用的な入力補完機能が実装できました。

## コードの解説

### 1. 入力候補の準備

```python
# 入力候補（本来はDBから取得してもOK）
suggestions = ["Apple", "Banana", "Blueberry", "Cherry", "Grape", "Mango", "Orange", "Peach"]
```

ここでは固定のリストを使っていますが、実際のアプリケーションではデータベースから動的に取得するケースが多いでしょう。

### 2. ページの基本設定

```python
st.set_page_config(page_title="入力補完サンプル", layout="centered")
st.title("🍓 入力補完付きフォーム")
```

`set_page_config`でページのタイトルとレイアウトを設定しています。`layout="centered"`はモバイル表示でも見やすくするための設定です。

### 3. 入力補完の実装

```python
# 補完候補から選択
selected = st.selectbox("フルーツを選ぶか入力してね", [""] + suggestions)
```

Streamlitの`selectbox`は、ドロップダウンリストから選択する機能を提供します。`[""] + suggestions`とすることで、空の選択肢を先頭に追加しています。これにより「何も選択しない」状態を作ることができます。

### 4. カスタム入力の実装

```python
# 新しい値を入力したい場合
if selected == "":
    custom_value = st.text_input("新しいフルーツ名を入力")
else:
    custom_value = selected
```

リストから選択した場合はその値を使い、空の選択肢（`""`）を選んだ場合は、テキスト入力欄を表示して自由に入力できるようにしています。

### 5. 入力確認と検証

```python
# 入力確認
if st.button("✅ 決定"):
    if custom_value:
        st.success(f"選ばれたフルーツ：**{custom_value}**")
    else:
        st.warning("何か入力してください！")
```

決定ボタンをクリックしたときに入力値の検証を行います。値が空でなければ成功メッセージを表示し、空の場合は警告メッセージを表示します。`st.success`と`st.warning`を使うことで、視覚的にもわかりやすいフィードバックを提供できます。

## 発展的な改良案

このシンプルな実装をベースに、さらに機能を追加することもできます：

1. **検索機能の強化**: 
   - `st.selectbox`の代わりに`st.multiselect`を使って複数選択に対応
   - 正規表現や曖昧検索による入力補完の改善

2. **リアルタイム入力検証**:
   - 入力値に対する即時バリデーション
   - 入力形式のガイダンス表示

3. **データの永続化**:
   - 入力された新しい値をデータベースに保存
   - ユーザーごとに過去の入力履歴を記憶

4. **UI/UXの改善**:
   - CSSカスタマイズでモバイル表示を最適化
   - キーボードショートカットの追加

## まとめ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2648069/7cbf1c4a-541d-40b7-93ae-c85c5f4b05b7.png)

Streamlitを使うことで、わずか数行のPythonコードで実用的な入力補完機能を実装できました。特に以下のポイントがポイントです：

- `selectbox`と条件分岐を組み合わせた柔軟な入力方法
- モバイル対応を意識したシンプルなUI設計
- 適切なフィードバックによるユーザー体験の向上

今回の実装はあくまで基本ですが、実際のアプリケーションに合わせてカスタマイズすることで、より高度な入力補完機能を構築できます。

## 注意事項

- **入力補完の仕組みについて**  
  本記事のサンプルでは、Streamlit の `selectbox` を使った入力補完を実装していますが、これはドロップダウンメニューに静的な候補を表示する形式です。ユーザーが文字を入力した際に、入力内容に応じて候補を動的に変えたり、リアルタイムでドロップダウンが自動的に表示されるオートサジェスト機能（例：Google検索のような）は含まれていません。

- **自動サジェストの実現には制限がある**  
  Streamlit 標準の部品では、文字入力中にドロップダウンが自動的に開いて候補が絞り込まれるようなシームレスなオートコンプリートはサポートされていません。そういったUIを実現したい場合は、JavaScript や React で作られたカスタムコンポーネント、またはコミュニティ製の Streamlit 拡張コンポーネントの利用が必要です。

- **大規模データセットへの対応**  
  本記事では小規模な固定リスト（フルーツ名）を使っていますが、選択肢が数百〜数千件になると、パフォーマンスが低下したり、ユーザー体験が悪化する可能性があります。大量データを扱う場合は、候補を事前にフィルタリングする処理や、サーバーサイド検索の導入が推奨されます。

- **UI/UXのカスタマイズ制限**  
  `selectbox` や `text_input` などの標準ウィジェットは、スタイルや挙動のカスタマイズに限界があります。モバイル対応のUIをより柔軟に調整したい場合や、インタラクティブな入力補完体験を追求する場合は、CSSの調整や外部コンポーネントの導入が必要になることがあります。

- **拡張を見据えた設計を**  
  本記事の内容は基本的な実装例ですが、将来的により高度な補完機能を追加したい場合は、コンポーネントの置き換えや構成変更が発生する可能性があります。あらかじめ機能追加を見据えてコードを構成しておくと、保守性の高い設計になります。


## 参考リンク

- [Streamlit公式ドキュメント](https://docs.streamlit.io/)
- [st.selectboxのドキュメント](https://docs.streamlit.io/library/api-reference/widgets/st.selectbox)
- [Streamlitでのフォーム実装](https://docs.streamlit.io/library/api-reference/control-flow/st.form)

---

フルーツ選択の例を使いましたが、この方法は商品名、地域名、タグなど様々な入力補完に応用できます。皆さんのプロジェクトでカスタマイズして活用してみてください！


## 免責事項
本記事の作成にあたり、文章や図解の生成にClaude Sonnetを活用しました。最終的な編集と確認は筆者が行っています。