Power Apps でツリービュー（アコーディオンメニュー）を作ってみた

## 序
![F6dtCE5aMAAfhr9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952933/e91bec5a-cccb-d0c5-d57d-9e9ce7801877.png)
Power Apps で上の画像のような機能を実装できないものか考えてみました。AさんをクリックすればAさんに関する情報（今回は日付データ）が表示され、Bさんをクリックすれば、Aさんと同様に情報が展開されるようなリストです。

何の気ない思い付きに反応してくれたのが旧Twitterでお世話になっている[出戻りガツオさん](https://twitter.com/DemodoriGatsuo)、[七草あんこさん](https://twitter.com/ankoromochi7793)、[ヨウセイさん](https://twitter.com/youseibubu)…の３名でした。

出戻りガツオさんからは大まかな構造を、七草あんこさんからはコレクションが２つ必要なことを、ヨウセイさんからはトグルでの制御をヒントとして授かりました。記事の冒頭をお借りして御礼申し上げます。ありがとうございました。
https://qiita.com/h-nagao/items/73c5192c6f268383ff5e
記事を書き終えた後で、既にHiroさんがこれをネタにしていることを教えてもらいました。コチラの方が余計なコントロールを追加する必要もなく整然としている印象です。

## 本題
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952933/09765a71-4042-0492-dddc-767d3b26f47b.png)

まずは大まかな流れを書いておきましょう。

1. リストの見出しとなる、名前フィールドの重複を除いたレコードをコレクション（colBrowse）として取得し、その親の持っている日付データを別のコレクション（colDate）として取得します
1. 次に、その colDate のレコードをトグルで削除したり追加したりできるようにします
1. 最後に、colDate の持つ日付データを ThisItem 演算子で呼び出せば、今回の目的は達成されます

これを読んでも「は？」という人は、以下の手順をゆっくり読んで実装してみましょう。

### データを用意し、親（colBrowse）を表示する
以下のフィールドを有したテーブルを用意します（筆者はSPOリストを使いました） 

- DataSource（リスト名）
- Name（テキスト型データ）
- Date（日付型データ）

リストを作成したら、いくつかダミーのデータを入れておきましょう。全て用意ができたら「空のキャンバスアプリ」を作成し、そのデータをアプリと紐付けます。

この連携までが終わったらボタン（Button1）を追加し、OnSelect プロパティに以下の設定を行います。
~~~
ClearCollect(colBrowse,DataSource,Date)
~~~
次に「高さが伸縮可能な空のギャラリー（galList）」を追加し、Items プロパティに以下の設定を行います。
~~~
Distinct(colBrowse,Name)
~~~
最後に、galList のテンプレートセルに、ラベル（lblName）を追加し、Text プロパティに以下の設定を行います。
~~~
ThisItem.Value
~~~
以上で、親データの作成が完了しました。アプリを実行して名前が一覧で表示されていればOKです。
### 日付データ（colDate）を表示する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952933/7ae86f2c-42b4-9099-2c97-707b1fdd8dd6.png)
galList のテンプレートセル内に日付データを取得するためのトグル（Toggle1）を配置します。このトグルは、①ギャラリー内の最前部に配置し、②テンプレートセル一杯に拡大し、③無色透明に設定しておきます（※非表示ではない点に注意）
![F6dtCE5aMAAfhr9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952933/ead6b06e-b81c-d730-353d-1ca86c6a914f.png)
次に、既定値が false になっていることを確認し、OnCheck プロパティ以下の設定を行います。
~~~
Collect(colDate,Filter(colBrowse,Name = ThisItem.Value))
~~~
これは、トグルのチェックが入った時に colBrowse の Value フィールド（＝ Name ）と一致するレコードを colDate としてコレクションに収めています。

ちなみに、ここで ClearCollect 関数を使用してしまうと、Toggle1 の値が true になる毎に新しくレコードを追加し直す動作となるため、同時に複数の情報を展開できなくなってしまいます。この観点から、Collect 関数の方を使用しています。

しかし、このままだと何度も展開したり折りたたんだりすることで同じレコードを取得し続けることになってしまいます。Toggle1の値が true の時に Collect 関数が作動するからです。

したがって、折りたたんだ時、つまり、トグルの値が false になった時は、そのレコードだけが colDate から消去されるように設定する必要があります。ここで Remove 関数の出番です。今度は、Toggle1 の OnUnCheck プロパティに、以下の設定を行います。
~~~
Remove(colDate,Filter(colDate,Name = ThisItem.Value))
~~~
この設定により、クリックした項目のみが消去されるようになりました。Clear 関数を使用しないように注意してください。

ここまで設定できたら、colDate を表示するための「空の垂直ギャラリー（galDate）」を配置します。界隈で有名（？）な Gallery in Gallery というヤツです。galDate の Items プロパティには以下の設定を行います。

~~~
Sort(Filter(colDate,Name = ThisItem.Value),Date,SortOrder.Descending)
~~~
ここで Sort 関数は不要ですが、リストを展開した時に最新のデータから順に表示されると嬉しいと思うので追加しておくと便利です。設定が完了したら、galDate のテンプレートセル内にラベル（lblDate）を挿入し、Textプロパティに以下の設定を行います。
~~~
ThisItem.Date
~~~
これでリストの大枠は完成です。このリスト内で選択した項目の編集作用や詳細を表示したい場合は、lblDate に加えてアイコン（例：icoEdit）などを挿入して設定を行います。その設定の方法は割愛しますが、色々な記事は出回っているので各自で設定できるはずです。がんばってください。
### 見た目を整える
最後に、展開していることを視覚的に示すアイコンを galList のテンプレートセル内に挿入します。１つ目のアイコン（icoFilterOFF）として「逆『く』の字」を入れ、その Visible プロパティに以下の設定を行います。
~~~
If(Toggle1.Value=false,true,false)
~~~
Toggle1 の値が false の時に表示されて欲しいアイコンなので、上のような条件分岐となります。一方、２つ目のアイコン（icoFilterON）は、Toggle1 の値が true の時に表示されて欲しいものとなります。

「下向き『く』の字」のアイコンを挿入したら、以下の設定を行います。
~~~
If(Toggle1.Value = false,false,true)
~~~
これで見た目もプルダウンっぽくなりました。

最後に、galDate の Height プロパティもレイアウトを整えます。レコードの数に応じてサイズが変更されるようにします（※ヨウセイさんありがとうございました）
~~~
(Self.TemplateHeight+Self.TemplatePadding)*Self.AllItemsCount
~~~
## 結
さて、ひょんな思い付きでしたが色々な方々が反応してくださいました。今回もですが、Power Platform のコミュニティからは何かしら享受してばかりですので、こうして記事の執筆で還元していく必要がありますね。久しぶりで楽しかったです。

いつも市民開発者育成に関する備忘録や情報提供ばかりでしたが、今後も技術的なネタも還元できたらと思います。それでは。

## 付録
- 出戻りガツオさんのプルダウンリスト
https://twitter.com/DemodoriGatsuo/status/1704490573292269998
- ヨウセイさんのプルダウンリスト
https://twitter.com/youseibubu/status/1704473627058712871/video/1