Posted at

Node-redのmustacheテンプレート中でeval的な事をしたい時はLambda式を使うと嬉しいです


前提

Node-redでHTMLを動的に生成したい場合に一応Mustacheテンプレートまでは使って見たけれど、微妙に痒いところに手が届かないという人向けです。


状況

例えば、以下のようなPayloadを表にしたいとします。

{

"payload": [
{
"serial": 1,
"lank": "bronze",
"lastname": "tanaka",
"firstname": "taroh",
"phone": "090-0000-0000"
},
{
"serial": 2,
"lank": "gold",
"lastname": "suzuki",
"firstname": "jiroh",
"phone": "090-0000-0001"
},
{
"serial": 3,
"lank": "silver",
"lastname": "yamada",
"firstname": "hanako",
"phone": "080-0000-0000"
}
]
}

上記のJSONだった場合、mustacheテンプレートは

{{#payload}}

<tr>
<td>{{serial}}</td>
<td>{{lank}}</td>
<td>{{lastname}}</td>
<td>{{firstname}}</td>
<td>{{phone}}</td>
</tr>
{{/payload}}

とやれば、(前後のtableタグと一行目はまぁどこかに書いてあるとして)

serial
lank
lastname
firstname
phone

1
bronze
tanaka
taroh
090-0000-0000

2
gold
suzuki
jiroh
090-0000-0001

3
silver
yamada
hanako
080-0000-0000

みたいな表になるためのHTMLが出来てくるわけです。

ここまではまぁ普通の便利な使い方です。


ここで、例えばLankが、外部キー的になってた場合どうするのか?

つまり、

serial
lank
lastname
firstname
phone

1
3
tanaka
taroh
090-0000-0000

2
1
suzuki
jiroh
090-0000-0001

3
2
yamada
hanako
080-0000-0000

serial
lankname

1
gold

2
silver

3
bronze

みたいなデータ構造になるってわけです。まぁ普通はこういう構造の方が多いですよね。

で、そのときにどうやってスマートに描画するか?

そこでLambda式を使います。

まず、templeteノードよりも前にFunctionノードを用意して、

msg._render = function(){

return function(text, render){
return render("{{" + render(text) + "}}") ;
}
};
return msg;

としておきます。

あと、前提となるデータとして

{

"payload": [
{
"serial": 0,
"lank": 2,
"lastname": "tanaka",
"firstname": "taroh",
"phone": "090-0000-0000"
},
{
"serial": 1,
"lank": 0,
"lastname": "suzuki",
"firstname": "jiroh",
"phone": "090-0000-0001"
},
{
"serial": 2,
"lank": 1,
"lastname": "yamada",
"firstname": "hanako",
"phone": "080-0000-0000"
}
]
}

ってのと(さっきとはlankの中身が変わってます)、それに加えて

{

"lanklist": [
{
"serial": 0,
"lankname": "gold"
},
{
"serial": 1,
"lankname": "silver"
},
{
"serial": 2,
"lankname": "bronze"
}
]
}

というのも用意しておきます。

その状態で、mustacheを以下のようにします。

{{#payload}}

<tr>
<td>{{serial}}</td>
<td>{{#_render}}lanklist.{{lank}}.lankname{{/_render}}</td>
<td>{{lastname}}</td>
<td>{{firstname}}</td>
<td>{{phone}}</td>
</tr>
{{/payload}}

このlanklist.{{lank}}.lanknameのところを{{#payload}}のリストとして評価すると、最初はlanklist.0.lanknameというテキストになります。それを{{#_render}}の箇所でlambda式に突っ込むわけです。

中身はrender("{{" + render(text) + "}}")なので、つまりrender("{{lanklist.0.lankname}}")を評価せい、という事で、めでたくgoldという文字列に置き換わってくれるという事になります。


以上ですが、、

ぶっちゃけ、今回の実装であればlanklistのserialは管理上の為だけで、無いなら無いでもOKのはずなのです。。。

JSONata的な検索ができるんならば、別な表現も出来そうですね。。

まぁその内良いアイデアが浮かぶと思いますので、その時までは一旦これで勘弁してください。。

では。