こんにちは、あんこ先生です。
前回は、投稿がずらっと並ぶタイムライン画面を作りました。
見るだけの画面から、今回は反応できる画面にしていきましょう。
そう、いいね機能です。
一度押したら青くなって、もう一度押すと取り消せる。あのトグルを作ります。
まだ読んでいない人は、先にタイムライン画面の回を作っておいてくださいね。
いいねの仕様を決めておく
コードを書く前に、動きをはっきりさせておきましょう。
・ひとりが同じ投稿に押せるのは1回だけ
・もう一度押したら取り消せる
・投稿ごとに、いま何件いいねが付いているか出す
この「1回だけ」というのが、地味に考えどころです。
ボタンを押した回数を数えるだけなら簡単なのですが、それだと同じ人が連打できてしまいますからね。
データの持ち方をおさらい
第1回で作った Likes リストを思い出してください。
列は PostID ひとつだけ、という驚くほどシンプルなリストでした。
| 列 | 入るもの |
|---|---|
| PostID | どの投稿へのいいねか |
| 登録者 | 誰が押したか(SharePointが自動で記録) |
「誰が押したか」は 登録者 が勝手に入るので、列を足す必要がありません。
つまり「この投稿IDで、この人の行があるか」を調べれば、いいね済みかどうかが分かる、というわけです。
いいねを押したら1行足す。取り消したらその行を消す。それだけです。
まず「自分がいいね済みか」を調べる
さて、ここからが本番です。
タイムラインの各行で「自分はこの投稿にいいねしたっけ?」を判定したいわけですが、行ごとに毎回Likesを調べにいくと、行の数だけ問い合わせが走って重くなります。
そこで、画面を開いたときに、自分がいいね済みの投稿IDをまとめて取ってきておきます。
画面 scrTimeline の OnVisible に、こちらを入れてください。
//画面 scrTimeline の OnVisible(自分がいいね済みの投稿IDをまとめて取得する)
//各行で毎回 Likes を調べるより軽く、委任の警告も避けやすい
ClearCollect(
colMyLikes,
ForAll(
Filter(Likes, Author.Email = User().Email),
{ Value: PostID }
)
)Likesを「自分が登録した行」だけに絞って、その PostID を colMyLikes に並べています。
ここで、ひとつ大事なところがあります。
ForAll でわざわざ { Value: PostID } という形に詰め替えているところです。
ForAll そのものの使い方は、繰り返し処理ならコレ!ForAll関数の便利な使い方にまとめてあります。
なぜ列名を Value にするのか

素直に書くなら、こうしたくなりますよね。
//一見よさそうだけど、あとで困る書き方 Filter(Likes, Author.Email = User().Email).PostID
これでも投稿IDだけが並んだ入れ物にはなります。
ただし、このときの列名は PostID です。
いっぽう、あとでいいねを押したときには、コレクションにも1件足しますよね。
そこで Collect を使うと、列名を自分で決めることになります。
ここで { Value: … } と書いてしまうと、最初に作った列名(PostID)と食い違ってしまうんですね。
・作るとき(ClearCollect)
・調べるとき(in で判定)
・足すとき(Collect)
・消すとき(RemoveIf)
ひとつでも違うと、足したぶんだけ判定から外れて「押したのに色が変わらない」といった動きになります。値をひとつだけ並べる入れ物は、列名を Value にそろえておくのが慣例です。迷ったら Value、と覚えておくとラクですよ。
コレクションの作り方や加工の仕方をおさらいしたい人は、複写!抽出!追加!結合!コレクションの加工方法もどうぞ。
いいねボタンを置く
では、ギャラリーの中にボタンを追加しましょう。
モダンボタンを置いて、名前を btnLike にします。
| プロパティ | 設定する式 |
|---|---|
| Icon | “ThumbLike” |
| Text | Text(ThisItem.LikeCount) |
| Layout | ButtonLayout.IconBefore |
| Appearance | ButtonAppearance.Transparent |
| Height | 32 |
| Width | 90 |
| X | 86 |
| Y | imgPost.Y + imgPost.Height + 6 |
Layout を IconBefore にすると、アイコンの右に文字が並びます。
そこに件数を出しているので、「👍 3」のような見た目になりますね。
Y座標は、前回おぼえた「ひとつ上の下端から積む」を守っています。
状態は色で表す
いいね済みかどうかを、見た目でも分かるようにしましょう。
Color にこちらを入れます。
//いいねボタン btnLike の Color(いいね済みなら青、まだならグレー) If(ThisItem.PostID in colMyLikes.Value, RGBA(0, 120, 212, 1), RGBA(120, 120, 120, 1))
さっき作った colMyLikes の出番です。
in は「その中に含まれているか」を調べる演算子で、ここでは「この投稿IDが、自分のいいね済み一覧に入っているか」を見ています。
モダンボタンのプロパティは、モダンコントロール ボタン(Button)の使い方にもまとめてあります。
押したときの処理を書く
いよいよ本丸です。
OnSelect に、こちらを入れてください。
//いいねボタン btnLike の OnSelect(押すたびに、いいねを付けたり外したりする)
//すでに押していれば取り消し、まだなら追加する
//画面をひらき直さなくても見た目が変わるよう、コレクションも同時に更新する
If(
ThisItem.PostID in colMyLikes.Value,
RemoveIf(Likes, PostID = ThisItem.PostID, Author.Email = User().Email);
Patch(Posts, ThisItem, { LikeCount: ThisItem.LikeCount - 1 });
RemoveIf(colMyLikes, Value = ThisItem.PostID),
Patch(Likes, Defaults(Likes), { Title: ThisItem.PostID, PostID: ThisItem.PostID });
Patch(Posts, ThisItem, { LikeCount: ThisItem.LikeCount + 1 });
Collect(colMyLikes, { Value: ThisItem.PostID })
)長く見えますが、やっているのは3つずつの作業を、2パターン書いているだけです。
Patch の基本を確認したい人は、Patch関数の使い方 基本編を先に読んでおくと分かりやすいですよ。
すでに押していたら(取り消し)
| やること | 使う関数 |
|---|---|
| Likesから自分の行を消す | RemoveIf |
| 投稿のいいね数を1減らす | Patch |
| コレクションからも消す | RemoveIf |
RemoveIf の条件がふたつ並んでいるのがポイントです。
「この投稿の行」かつ「自分が登録した行」に絞ることで、ほかの人のいいねを巻き込まずに済みます。
まだ押していなかったら(追加)
| やること | 使う関数 |
|---|---|
| Likesに自分の行を足す | Patch |
| 投稿のいいね数を1増やす | Patch |
| コレクションにも足す | Collect |
こちらも同じ3点セットで、向きが逆になっただけですね。
なぜコレクションも一緒に更新するのか
Likesへの登録だけなら、SharePointの側は正しくなります。
でも、画面の色を決めているのは colMyLikes のほうでしたよね。
ここを更新しないと、押したのに色が変わらない、という残念な動きになってしまいます。
そこで、SharePointとコレクションの両方を同時に更新しているわけです。
LikeCount のほうは、Patch で投稿そのものを更新しているので、件数の表示もその場で変わります。
区切り線の位置を直す
最後にひとつ、前回作った部分に手を入れます。
いいねボタンが画像の下に入ったので、区切り線 recDivider はその下にずらしましょう。
| プロパティ | 変更前 | 変更後 |
|---|---|---|
| Y | imgPost.Y + imgPost.Height + 16 | btnLike.Y + btnLike.Height + 12 |
これで、いちばん下の部品がまた区切り線に戻りました。
前回の「ドミノ倒し」の話を思い出してもらえると、なぜこの1行を直すだけで行の高さが正しくなるのか、すっと入ってくるはずです。
知っておきたいこと
動くようになったところで、この作りの性格も押さえておきましょう。
ほかの人のいいねは、すぐには映らない
colMyLikes は、画面を開いた時点のものです。
そのため、自分が押したぶんはその場で反映されますが、ほかの人が同じタイミングで押したいいねは、画面を開き直すまで出てきません。
部署内で25人ほどの利用なら、これで困ることはまずないと思います。
気になるようなら、更新ボタンを置いて OnVisible と同じ式を実行する、という手もありますね。
委任の警告が出たら
登録者 のようなユーザー列をメールアドレスで絞ると、委任の警告(青い下線)が出ることがあります。
これは「データが増えたときに、全部を正しく調べられないかもしれません」という注意書きです。
数千件を超えると影響が出てきますが、部署内のサンクスアプリならしばらくは平気でしょう。
委任そのものについては、黄色いアイツ、委任警告の回避方法でくわしく解説しています。
まとめ
今回はここまでにしましょう。
・「1人1回」は、LikesにPostIDと登録者の行があるかどうかで判定する。
・行ごとに調べにいかず、画面を開いたときに colMyLikes へまとめて取っておく。
・値をひとつ並べるコレクションは、列名を Value にそろえる。作る・調べる・足す・消すの4か所ぜんぶ。
・いいねを押したら、SharePointとコレクションの両方を更新する。片方だけだと見た目が付いてこない。
次の一手として、次回はいよいよ投稿画面を作ります。
アプリの中から「ありがとう」を送れるようにする回ですね。
送信先を選んで、メッセージを書いて、タグを付けて、画像も添える。
ここまで作ると、ようやくアプリの中だけで一周できるようになりますよ。
それでは、次の記事でお会いしましょう。


















・押すと付いて、もう一度押すと外れるトグル
・同じ人が二重にいいねできない仕組み