はじめに
研究で開発しているLINEBotで,取得したデータに応じてFlexMessageを動的に変化させて作成する必要がありました.しかし,その部分に関して記事があまり見つからなかったのでせっかくならと書くことにしました.
これがベストプラクティスという保証はできないです
実装環境
- node.js 18.12.1
- typescript 4.9.0
- @line/bot-sdk 7.5.2
つくりたいもの
今回では例として次のようなFlexMessageを作るとします.
FlexMessageSimulatorで適当に作ったものです.
データの数によってリストの列数が変化したり,カルーセルのバブル数を増やしたりといった内容です.
実装
では実際に,このFlexMessageを作成するコードを書いていきます
getListFlexMessage.ts
// FlexMessageやFlexBubbleの型をインポート
import {FlexBubble, FlexMessage} from "@line/bot-sdk";
function getListFlexMessage(data: string[]): FlexMessage {
// リストを保持する配列
const contents: FlexBubble[] = [];
// 配列を10要素ごとの配列に分割し,それぞれに合わせてリストを作成する
arrayChunk(data, 10).forEach((events) => {
// 作成したリストを追加
contents.push(getListContent(events));
});
// 作成したFlexMessageを返す
return {
"type": "flex",
"altText": "イベントリスト",
"contents": {
"type": "carousel",
"contents": contents,
},
};
}
// データに合わせたリストの作成
function getListContent(data: string[]): FlexBubble {
// リストの要素を持つ配列
const listItems: any = [];
// データの数だけループを回してリストの要素を作成する
data.forEach((itemData) => {
listItems.push(getListItem(itemData));
});
// リストを返す
return {
"type": "bubble",
"header": {
"type": "box",
"layout": "vertical",
"contents": [
{
"type": "text",
"text": "イベントリスト",
"align": "center",
},
],
},
"body": {
"type": "box",
"layout": "vertical",
"contents": listItems,
},
"styles": {
"header": {
"backgroundColor": "#f0f0f0",
},
},
};
}
// データに合わせたリストアイテムの作成
function getListItem(data: string): any {
return {
"type": "box",
"layout": "vertical",
"contents": [
{
"type": "text",
"text": data,
"margin": "md"
},
{
"type": "separator"
}
]
}
}
// 配列を指定した長さの配列に分割する
function arrayChunk<T>(array: T[], size: number): T[][] {
if (size <= 0) return [[]];
const result = [];
for (let i = 0, j = array.length; i < j; i += size) {
result.push(array.slice(i, i + size));
}
return result;
}
コンテンツの内容をオブジェクトで作成して配列に格納していくのが基本的な方法です.
おわりに
以上でFlexMessageの動的作成は以上です.
戻り値のオブジェクトを使いたい形式に変換して利用すれば,複雑なFlexMessageも作ることができるんじゃないかなと思います.
ただFlexMessageにはデータ量に上限(バブルは30KB,カルーセルは50KB)があるので利用する際は気を付けてください.