#PowerApps  の Componentsについて紹介 (実験的な機能)

#Componentsって何？
PowerAppsの~~プレビュー環境向けに配信された~~ プレビュー機能です。
※現在は通常の環境でもアプリごとに有効にできます。

アプリの設定で実験的な機能で有効にすることで利用可能になります

![C61AA40B-C37B-4881-A326-B0453434D194.jpeg](https://qiita-image-store.s3.amazonaws.com/0/202779/93ece9e3-900c-7ca6-6e9c-b41d0aed4cae.jpeg)

記載されている通り、アプリやスクリーン間で再利用可能なコントロールの集合です。
これまではスクリーン間であってもグループ化してコピーしたり(その場合はコントロール名が”_1”のようになっていました)、アプリ間でもコピーペーストで対応していましたが、このComponentによって共通部品の再利用性が格段に向上しました。
また、スクリーン側からはComponent内のコントロールは隠蔽されているので、せっかくのグループを破壊してしまわないという点でもアプリ作成に恩恵があります。

#作り方と使いかた
早速プレビュー環境でコンポーネントを作成してみます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202779/dbdad6f2-bf15-b96c-339f-38b3ea4faee1.png)

##作る
コンポーネントを有効にしたアプリでは、画面左のスクリーンとコントロールのツリービューに新たなタブ”コンポーネント”が表示されています。
![treev.png](https://qiita-image-store.s3.amazonaws.com/0/202779/1bdd4517-e6b7-417e-4cef-7209377dd551.png)

コンポーネントの追加/編集はこの"コンポーネント"をクリックし、スクリーンおよびその中のオブジェクトとは別の画面で行います。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202779/f22f6357-8456-474e-e3a9-43997375caa9.png)

複数のコンポーネントがツリービューで表示されています。
コンポーネントはそれ自身にサイズの定義を持っています。スクリーンとは異なり、このサイズはコンポーネントごとに定義ができます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202779/b82c86bb-10c0-5a49-da48-cf6132cbfeb3.png)
また各種プロパティも設定可能で、小さな独立したスクリーンのような構成になっています。

##オブジェクト追加
スクリーンにオブジェクトを追加する場合と同様に、各種ラベルやコントロールをコンポーネント内に配置できます。
ここでは後のテストのためにボタンとラベルを1つ追加しました。また、もとのスクリーンとの境界がわかりやすいようにFillプロパティで背景色を指定しています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202779/604787c3-e06e-3ff4-1f08-5d91e5d92a78.png)

##スクリーンに配置する
作成したコンポーネントをスクリーンに配置する場合には赤枠内のボタンで他のコントロール同様に追加します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202779/7c437992-8a33-b05b-8ca2-47f1ddc8a2f2.png)

**注意**:コンポーネントは、それ自身に名前の定義を持っていますが、スクリーンに配置した際には、スクリーンごとに異なる名前をつけなければなりません。(同じ”ギャラリーコントロール”でもスクリーンそれぞれ名前を変えるのと似ています)

左側のツリービューを見てわかる通り、コンポーネントの内部にあるラベルやボタンは、スクリーン側からは表示されないようになっています。また中の要素にスクリーン側からアクセスしようとしても候補に表示されません。
Component1.Label1のような指定は不可。

##Component内の要素とスクリーン側とで名前の一意性は？
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202779/ad1ab5bb-c64c-6167-64ef-03e6175ba6c0.png)
コンポーネント内で利用しているLabel1という名前は、スクリーン側でも使用できません。スクリーン側からは隠蔽されていますが、一方で、名前を一意にしなければならないのは変わらないようです。

##変数の受け渡し

###コンテキスト変数
画面内で閉じる変数、コンテキスト変数が、スクリーンに配置したコンポーネントではどのように作用するのかを確認します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202779/11aa0fb8-4d73-a2ae-d560-b5ae54fe5221.png)
早速躓きました。コンポーネント内ではUpdateContext関数はサポートされていないようです。
当然、スクリーン側で更新したコンテキスト変数も、コンポーネント内には作用しませんでした。
###グローバル変数
面白いことに、コンポーネント内ではグローバル変数の利用は可能です。なので、コンポーネント内で何かの変数を利用したい場合にはグローバル変数を利用する必要がありそうです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202779/89e736cd-813a-d269-6f95-adc9222f0baa.png)

###Collection
ここまで変数がだめだったので、少し諦め気味ですが、Collectionが受け渡されるかを確認します。
コンポーネント内のボタンでコレクションを生成し、Label1にコレクションのテキストを表示します。
スクリーン側でも、Label2にコレクションのテキストを指定しています。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202779/638b3de3-d279-f769-ff8b-b2d791243433.png)
成功！！Collectionはコンポーネント内とスクリーン側で共通のようです。
###カスタムプロパティを利用したデータの受け渡し
正攻法では、スクリーン側とコンポーネント側で値の受け渡しをする・コンポーネント内の要素にアクセスする場合、コンポーネントのカスタムプロパティを利用するようです。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202779/d7937e0d-0b3e-8f6a-0566-5d28b446d40a.png)

カスタムプロパティを作成する画面では、以下のように、
- 入力か出力か
- 名前（表示名・プロパティ名）
- データ型
を定義します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202779/95a298a6-4adb-5f0a-82db-8a394b2e031c.png)
試しに、入力として"input1"をテキスト型、出力として"output1"をテキスト型で定義します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202779/4535f587-e534-73da-8a18-509943fd291b.png)
スクリーン側からinput1というComp1のプロパティに値をセットできるようになりました。
あとはボタンのOnSelectなどに指定したコンテキスト変数の書き換え処理を入れれば
スクリーン側-->コンポーネントへの受け渡しは完了です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202779/d414e59f-29c4-b213-09fb-e1ed49ef8af4.png)

~~残念ながら、出力側についてはまったくわかりませんでした。このあたり、Twitterで聞いてみます。~~
[追記]
出力側について確認できました。
まずはグローバル変数を何か定義します。（ここではgvTest）
そのグローバル変数をコンポーネントの[詳細設定]にあるカスタムプロパティに設定します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202779/3ef90a92-d0ec-18f8-c765-2c7aa772ca56.png)
ここではテストとして、ボタンクリックでテキスト入力の値をセットするようにしています。
スクリーン側では、ラベルを用意し、そのTextプロパティに、<Component名>.<出力プロパティ名>（この場合はComp1_1.output1）を設定します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202779/e968f4a0-827b-c2a6-76d9-539da72660e4.png)
適当なテキストを入力し、ボタンをクリックすると、以下のようにスクリーン側にコンポーネントの変数の値を受け渡すことができました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202779/9ce590b9-6111-7ed0-99c1-d9f17ec78040.png)

*Twitterで教えてくださったMr.Dangに感謝です。

##データコネクションの取り扱い
Componentの中でSharePointからリストを参照できるか確認してみます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202779/f9fd81e5-4e63-a238-7ace-80e5ee2d412f.png)
結果、SharePointリストをデータソースに登録はできているものの、GalleryのItemsに指定しようとするとエラーになることがわかりました。

##アプリ間での再利用性
さて、コンポーネントの魅力であるアプリ間での再利用性について紹介します。
コンポーネントをほかのアプリで利用するためには、コンポーネントタブから、「コンポーネントをエクスポートします」を選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/202779/19156b7e-a797-1595-97ad-0b8915adf79e.png)
すると、[アプリ名].msappというファイルがダウンロードされます。
ほかのアプリで利用する際には、ダウンロードしたファイルを、今度は「コンポーネントをインポートします」からインポートしてください。
アプリ内で作成したコンポーネント（この場合Comp1とComp2）が新しいアプリでも利用可能になっています。

同じ名前のコンポーネントでなければ、エクスポートしたmsappファイルを複数個、1つのアプリにインポートできます。ですので、用途に応じたコントロール群をコンポーネントとして定義し、それらを組み合わせることで、新しいアプリを作成するというやり方が可能になるかなと思います。

#おわり
情報に更新がありましたら追記していきます。
Componentsをつかったスクリーン遷移用のサンプルアプリとComponentsファイルを以下のリンクに配置しました。ぜひ見てみてください。
https://1drv.ms/f/s!Arp1PnSG3hrVtUIRgEBxm43RUHTg