2014年12月23日火曜日

【JsRender】#parent

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

現在はJavaScriptによる画面レンダリングツール「JsRender」について連載しています。

今回も公式サイトに乗っていない秘密機能「parent」についてのご紹介です。

必要になるシチュエーション

#parentはfor文の真っ最中などで、親クラスを遡ってパラメータを取得する機能です。

例えば、私は「技術開発事業部」の所属ですが、同じ部にはメンバーが何人もいます。

  • 技術開発事業部:Aさん
  • 技術開発事業部:Bさん
  • 技術開発事業部:Cさん

こういう場合、データの持ち方によっては

  • 親クラス:部署
  • 子クラス:メンバー


というように、親子関係が生ずることになります。

このデータの持ち方で所属とメンバーを表現したい場合は、以下のような形式にするのが合理的です。


<div id="result"></div>

<script id="jsRenderTmpl" type="text/x-jsrender">
★{{:department}}
{{for members}}
<div>
・{{:name}}
</div>
{{/for}}
</script>

<script>
var data = {
  "department": "技術開発事業部",
  "members": [
      {"name": "Aさん"},
      {"name": "Bさん"},
      {"name": "Cさん"}
 ]
};

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>

しかしですね、場合によっては以下みたいな表示にしたいケースもあるわけですよ。


これは痛いんですよね。
何故なら、階層が違うから。

JSONの定義では「members」をfor文のスコープとして回していますので、membersより配下のデータを表示する場合は何も難しくありません。
普通に順を追って定義していけば表示出来ます。

しかし、membersより上のデータはスコープの中に入っていませんので、単純に取得することが出来ません。
今回のテーマである#parentはこういう場合に使用します。

#parentを活用

#parentは、まあ、タグ名から分かりますようにfor文のスコープの外にある親データを取ってくる機能です。
その実装方法はこちら。

<script id="jsRenderTmpl" type="text/x-jsrender">
{{for members}}
<div>
・{{:#parent.parent.data.department}}:{{:name}}
</div>
{{/for}}
</script>

<script>
var data = {
  "department": "技術開発事業部",
  "members": [
      {"name": "Aさん"},
      {"name": "Bさん"},
      {"name": "Cさん"}
 ]
};

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>

「#parent.parent.data.department」、これで「技術開発事業部」という値が取れています。

詳細解説

「あれ? parent2連打になってるのは何?」と思われたかと思います。

jsrenderでは「parent」を一個各毎に階層を一個遡るという意味になります。

今回の場合、スタート地点となるのはfor文の中のメンバーですから、


  • 単にそのレコードを出したい場合⇒「#data.name」(dataは通常省略)
  • その一個上のmembersを取りたい場合⇒「#parent.data」
  • その一個上のdataを取りたい場合⇒「#parent.parent.data」
  • 目的のdepartmentはdataの子供なので⇒「#parent.parent.data.department」

こういうわけです。
parentを連結することで一回一番上まで遡って、それからdepartmentを狙い撃ちするという段取りになるわけです。

parentを連発する辺り最初は戸惑いますが、分かってしまえば簡単なことですね。

終わりに

今回ご紹介した#parentは結構便利な機能です。
これを知らないと画面を表示する為にクラスを非正規化しなければならなくなり、手間も転送データ量も増えて大変ですからね。
上手く活用すれば開発効率もUPするでしょう。

ぜひマスターすることをオススメします。

2014年12月8日月曜日

【JsRender】#index

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

現在はJavaScriptによる画面レンダリングツール「JsRender」について連載しています。

さて、私はこの連載を行うに辺り、基本的に以下の公式サイトを読んで執筆しています。




しかし、どうも公式サイトのドキュメントに載っていない機能があるようです。
酷い話ですが、今回はその機能の一つ「#index」についてご紹介します。

for文のループ回数「#index」

普通、for文だと「for(int i=0;i;10;i++)」みたいに現在がfor文の何番目なのかを
iなどの変数で認識することが出来ます。

しかし、JsRenderのfor文はfor文と言ってもJavaで言う所の「for(String str : list)」の形式と言いますか、
つまり『配列全出力』の体を取っています。

この為、実装する上では通常のプログラミングである「i」に相当する変数が登場しません。
この為、「偶数行と奇数行で色を変えたい」みたいな、現在が何ループ目であるかを認識するには、挿入の元になっているJSONにパラメータを持たせる必要があるように見えます。

しかし、実は隠しパラメータとしてループの行数を持っていまして、それが「#index」です。

<script id="jsRenderTmpl" type="text/x-jsrender">
★{{:title}}
{{for members}}
<div>
・{{>#index}}:{{:name}}
</div>
{{/for}}
</script>

<script>
var data = {
  "title": "for文サンプル一覧",
  "members": [
      {"name": "碇シンジ",sex:"male"},
      {"name": "綾波レイ",sex:"female"},
      {"name": "ゼルエル",sex:"unknown"}
 ]
};

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>



ちゃんと行数が出ているでますね?

加工

では、この「#index」がちゃんと加工したりif文で使えたりするかも検証してみましょう。

まずは偶数/奇数の判定から。

<script id="jsRenderTmpl" type="text/x-jsrender">
★{{:title}}
{{for members}}
<div>
・{{>#index}}:{{:name}}:
 {{if #index %2 == 0}}
  偶数行
 {{else}}
  奇数行
 {{/if}}
</div>
{{/for}}
</script>

<script>
var data = {
  "title": "for文サンプル一覧",
  "members": [
      {"name": "碇シンジ",sex:"male"},
      {"name": "綾波レイ",sex:"female"},
      {"name": "ゼルエル",sex:"unknown"}
 ]
};

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>


バッチリですね。

では、「0からスタートではなく、1からスタートしたい」という場合は、
単純にindexに+1すればOKです。

<script id="jsRenderTmpl" type="text/x-jsrender">
★{{:title}}
{{for members}}
<div>
・{{>#index + 1}}:{{:name}}
</div>
{{/for}}
</script>

<script>
var data = {
  "title": "for文サンプル一覧",
  "members": [
      {"name": "碇シンジ",sex:"male"},
      {"name": "綾波レイ",sex:"female"},
      {"name": "ゼルエル",sex:"unknown"}
 ]
};

var template = $.templates("#jsRenderTmpl");

var htmlOutput = template.render(data);

$("#result").html(htmlOutput);
</script>



簡単ですね!

終わりに

この「#index」は、前述の通り無くてもJSON定義の方で回避可能です。
しかし、知っていると知らないとでは便利さが格段に違います。

何で公式サイトに載っていないのか謎ですが、ぜひ活用していきたいものです。

引き続き隠し機能を検証します。