はじめに
マシュマロで以下のような質問をいただきましたので、今回はこちらの回答をまとめた記事になります。
ちなみにこちらの質問内ででているリストのレーティング機能を利用してPower Appsでいいね機能を実装したアプリの解説は以下記事で紹介しています。
SPOリストにいいね機能を用いたアプリの開発に興味のある方はこちらを見ていただけますと幸いです。
いいね機能を実装するにあたり最低限必要な情報
いいね機能を実装するにあたり最低限以下の情報が必要になってくるかと思います。
- ユーザテーブル: ユーザの情報が保存されたテーブル。
->これはSPOリストを利用するのであれば、ユーザ列からユーザ情報を引っ張ってこられるので不要ですね。 - アイテムテーブル: 評価されるアイテムの情報が保存されたテーブル。
- 評価テーブル: ユーザがアイテムに対して行った評価を保存しておくためのテーブル。ユーザテーブルとアイテムテーブルをIDなどの一意な値の外部キーで参照するための列が必要です。
よって、SPOリストのレーティング評価機能を利用しないのであれば、
- アイテムテーブル
- 評価テーブル
の2つのリストを用意する必要がありますね。
一応リストの設定を共有しておくと、
アイテムテーブル
評価テーブル
-> ItemID
評価テーブルの'Rate'はいいねを実装するだけであれば不要です。
これはユーザが評価の点数まで記録したい場合に利用します。
また、'Comment'もなくてもいいです。
これはレビューコメントを利用したい場合に利用します。
いいね機能をアプリで実装する
完成形のアプリはこのような形式です。
構成としてはざっくり、
- いいねアイコン
-> 既に自身がそのアイテムに対していいねを押していた場合は塗りつぶしのいいねアイコンが、まだ押していない場合は塗りつぶされていないいいねアイコンが、それぞれ表示されるようにしています。 - いいねアイコンを選択
-> いいねアイコンを選択すると評価テーブルにレコードが作成、もしくは削除されます。
となっています。
ギャラリーのItems
にはアイテムテーブルを設定しています。
細かい設定もみていきましょう。
ユーザが対象のアイテムにいいねをしたかどうかの判断
ユーザ(アプリを利用しているユーザ)が対象のアイテムにいいねをしているかどうかは、評価テーブル(ItemsRatingLists)を確認すればわかります。
評価テーブルには、
- どのアイテムに対する評価か?
- 誰が評価したか?
が最低限含まれるようにしていますので、これら2つの情報でフィルタしてあげればいいね済みかどうかを判断できますね。
よって、以下のような式で判断が可能です。
IsBlank(LookUp(ItemsRatingLists, ItemID.Value = Text(ThisItem.ID) && User.Email = User().Email))
この際に注意が必要な点として、'ItemID'列は参照列ですので設定されている値を取りたい場合はValue
を参照してあげる必要があります。
また、この値はテキスト型として扱われてしまいます。
この問題を解消するために、フィルタ条件のアイテムID(ThisItem.ID
)をテキスト型に変換して比較してあげています。
なお、比較元のItemID.Value
を数値型に変換してしまうと以下のように委任に関する警告が出ます。
ユーザ列('User')は、ここはレコード形式で値が保持されます。
フィルターを行いたい場合は、このようにユーザ列内のフィールドと比較する必要があるので、ユーザ列を利用する際は覚えておいてください。
今回は一意な値であるユーザのメールアドレスでフィルタしています。
Icon
に実際に設定している式はこちらです。
If( IsBlank(LookUp(ItemsRatingLists, ItemID.Value = Text(ThisItem.ID) && User.Email = User().Email)), Icon.ThumbsUp, Icon.ThumbsUpFilled )
対象のアイテムがいいねされている数のカウント
対象のアイテムがいいねされている数のカウントであれば、誰がいいねしたか?の情報は不要なので、対象アイテムのIDでフィルタしてその数をカウントしてあげればよいですね。
ただし、カウントを行う関数であるCountRows 関数は委任できません。
委任ってなに?という方はこちらの公式ドキュメントを参照ください。
キャンバス アプリでの委任について - Power Apps | Microsoft Learn
委任が行えないと、Power Appsのデータ行の制限分だけのレコードをリストからPower Appsに取得してから、Power Apps上で処理が行われてしまいます。
ただしフィルタ条件に関しては委任が可能なので、リスト側でフィルタした結果をPower Appsに渡して欲しいです。
ということで、以下の式とすることで上記問題を解決させます。
With( {items: Filter(ItemsRatingLists, ItemID.Value = Text(ThisItem.ID))}, CountRows(items) )
細かい話ですが、これで処理可能なアイテム数の上限が変わってきます。
いいね機能を実装する
肝心のいいね機能の実装です。
処理としては、
- まだいいねしていないユーザがいいねをした場合
-> 評価テーブルに情報を登録 - 既にいいね済みのユーザがいいねを押した場合
-> 評価テーブルから対象の情報を削除
で実現可能です。
注意する点としては、ユーザ列と参照列へのアイテムの登録に関してですかね。
ユーザ列では以下のようなレコードが必要になってきます。
{ Claims: [ユーザのClaim], Department: [ユーザの部署], DisplayName: [ユーザの表示名], Email: [ユーザのメールアドレス], JobTitle: [ユーザのJobTitle], Picture: [ユーザのプロフィール画像] }
参照列では以下のようなレコードが必要になってきます。
{ Id: [参照先のレコードのID] Value: [参照先の値] }
これらに注意したうえで、式を設定すると以下のようになります。
If( IsBlank(LookUp(ItemsRatingLists, ItemID.Value = Text(ThisItem.ID) && User.Email = User().Email)), Patch( ItemsRatingLists, Defaults(ItemsRatingLists), { User: { Claims: "i:0#.f|membership|" & Lower(User().Email), Department: Office365ユーザー.MyProfileV2().department, DisplayName: User().FullName, Email: User().Email, JobTitle: Office365ユーザー.MyProfileV2().jobTitle, Picture: User().Image }, ItemID: { Id: ThisItem.ID, Value: ThisItem.ID } } ), RemoveIf(ItemsRatingLists, ItemID.Value = Text(ThisItem.ID) && User.Email = User().Email) )
これでいいね機能の実装ができました!
おわりに
SPOリストの標準機能利用するのとどちらがやりやすいか?は好みによるところもあるのでどちらがよいか?は一概には言えないですが、この実装方法の方が処理としてはシンプルに済むんじゃないでしょうか?
また、Dataverseなどのレーティング機能がない(ないよね?)データソースを利用する場合はこのやり方が使えるんじゃないかな。と思います。
質問や疑問点、指摘などありましたら遠慮なくどうぞー