Power Appsの小ネタ テンプレのとあるパーツが便利

# はじめに
`Power Apps`でテンプレートを使うことはありますか？
私はキャンバス アプリを作成する中で **「+ 新しい画面」の`電子メール`がとても気に入っています。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/dc5e0abb-924e-38f3-b545-f658c65951a7.png)

下記のような画面が出てきます。`終了日`はおそらく誤訳ですね。
**この中の赤枠の検索ボックスが特に気に入っている機能です。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/ba6387e4-b7b0-76ce-afb8-dd5fd6680c37.png)

# 構成
クラシック コントロールで基本的に構成されています。

```plaintext:テンプレートのパーツ
  +-- PeopleBrowseGallery1 ユーザー検索結果を表示する垂直ギャラリー
  |     |
  |     +-- Separator1 各ユーザーアイテムの間に表示される区切り線
  |     |
  |     +-- Subtitle1 検索されたユーザーのメールアドレスを表示
  |     |
  |     +-- Title2 検索されたユーザーの名前
  |     |
  |     +-- Rectangle2 選択されたユーザーを枠線で囲む
  |
  +-- EmailPeopleGallery1 選択したレコードを表示するギャラリー
  |     |
  |     +-- iconRemove1 リストからレコードを削除するためのアイコン
  |     |
  |     +-- Title1 選択されたユーザーの名前
  |     |
  |     +-- Rectangle1 選択されたユーザーの背景
  |
  +-- SearchIcon1 検索アイコン
  |
  +-- TextSearchBox1 テキスト入力
```

全て`クラシック コントロール`で構成されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/12881a66-7cbb-52cd-10f7-1b3cd87fcc4c.png)

この画面は`ユーザー検索`からメールを送信する機能を目的としていますが、
 - 検索結果をコレクションに格納し、ギャラリーで表示する
 - コレクションに格納されたレコードをギャラリーで一覧化する

上記の機能を持っています。`テキスト入力`と`🔍アイコン`の組み合わせで、何を意図したものなのか、ユーザーフレンドリーであることが好みです。

# なぜこれが好きなのか
こちらが好きな理由は、コントロール単体で`検索`と`複数選択`をサポートする[コンボボックス](https://learn.microsoft.com/ja-jp/power-apps/maker/canvas-apps/controls/control-combo-box)が個人的に扱いづらいな、という課題感を持っているからです。

https://learn.microsoft.com/ja-jp/power-apps/maker/canvas-apps/controls/control-combo-box

 - `Default`プロパティと`DefaultSelectedItems`が入り混じっていること
 - `SelectMultiple`、`SearchFields`の設定がリセットされがちなこと
 - 境界半径をコントロールできないこと

上記が個人的にうーむ🧐です。
既定値を設定する`DefaultSelectedItems`についても、「あれ、これ何入れれば上手く反映されるんだったかな」と沼にハマることが良くあります。

:::note info
クラシック コントロールを前提として記載しています。
モダンは確かに見た目が良く使いたいです。しかしあくまでプレビュー機能です。`2024/12/25` 現在
実稼働を鑑みた際に、（私は）モダン コントロールの活用を避けてます。
:::

# 各パーツの数式がテクニカル
紹介したパーツの数式も解説させてください。

```javascript:PeopleBrowseGallery1のItems
/*Only use Office 365 Users operation if user has started searching*/
If(
    !IsBlank(Trim(TextSearchBox1.Text)),
    'Office365ユーザー'.SearchUser(
        {
            searchTerm: Trim(TextSearchBox1.Text),
            top: 15
        }
    )
)
```

[Office365ユーザー.SearchUser](https://learn.microsoft.com/ja-jp/power-apps/maker/canvas-apps/connections/connection-office365-users#search-for-users)が若干古い記法ですが、検索の書き方ってこうするのかと非常に勉強になります。

https://learn.microsoft.com/ja-jp/power-apps/maker/canvas-apps/connections/connection-office365-users#search-for-users

`Visible`は、テキスト入力が空白でないとき映るように設定されています。

```plaintext:Visible
!IsBlank(Trim(TextSearchBox1.Text))
```

またこのギャラリー内に位置するテキストラベル`Title2`には
```javascript: Title2のOnSelect
/*Select user, clear search contents and if this user hasn't been added to MyPeople collection, add them*/
Concurrent(
    Set(
        _selectedUser,
        ThisItem
    ),
    Reset(TextSearchBox1),
    If(
        Not(ThisItem.UserPrincipalName in MyPeople.UserPrincipalName),
        Collect(
            MyPeople,
            ThisItem
        )
    )
)
```

並列処理を実行する[Concurrent 関数](https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-concurrent)を使い
 - [選択されたレコードをグローバル変数に格納](https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-set)
 - [テキスト入力のリセット](https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-reset)
 - [コレクションの存在チェックを経て、アイテムを格納する](https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-clear-collect-clearcollect)

上記を実行しています。非常に美しいです。

https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-concurrent

https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-reset

https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-logicals

https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-clear-collect-clearcollect

https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/operators#in-and-exactin-operators

選択されたレコードは、`折り返しの数`が`4`に設定されたギャラリー コントロールで見やすく整理されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/0b3e80ef-0e5f-eb83-3f1f-4043ede7ffb7.png)

この折り返しの数に合わせて[CountRows 関数](https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-table-counts)と組み合わせた高さ設定も推しのポイントです。

https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-table-counts

```javascript:Height
/*Height adjusts to number of items in gallery*/
Min(
    (Self.TemplateHeight + Self.TemplatePadding * 2) * RoundUp(
        CountRows(Self.AllItems) / 4,
        0
    ),
    182
)
```

アイテムを削除する`icoRemove1`の`OnSelect`ではコレクションの操作のツボである[Remove 関数](https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-remove-removeif)も含まれています。

```javascript:OnSelect
Remove(
    MyPeople,
    LookUp(
        MyPeople,
        UserPrincipalName = ThisItem.UserPrincipalName
    )
)
```

https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-remove-removeif

https://learn.microsoft.com/ja-jp/power-platform/power-fx/reference/function-filter-lookup

全体的にコントロールの線を補足し、枠線・アイコンカラーを`rgba(105,105,105,1)` `Color.DimGray`、境界半径を`8`で統一することが私の好みです。
この修正だけで、安定的な検索機能をサクっと作れます。

■ 検索
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/4dccb0c3-e52d-40ae-23eb-55f8a280a239.png)

■ 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2734332/c3b0f667-bcea-7238-0bb9-639a371dc955.png)

私はコンポーネント化して何度も使っていたりします。(なんども一から作った記憶がありますが)

# おわりに
今回は衝動的に小ネタを記載しました。
テンプレートを観察していると、**Microsoftの猛者がこだわって作ったのかな**という妄想も膨らんで楽しいですね。

使いやすいヒントは意外と身近に転がっていたりします。
興味があるときに見てみてください。


https://learn.microsoft.com/ja-jp/power-platform/power-fx/formula-reference-canvas-apps