前人未踏の領域へ アプリ開発編

Android, iOSアプリ開発に関する調査メモ置き場。ほとんどAndroid。はてなダイアリーから移行したため古い記事にはアプリ以外も含まれます。

親のコンテキストのデータを参照する

Handlebarsではeachループを使って条件文の中に入るとコンテキストが変化し、パス名の記述の繰り返しを避けることができる。しかし、親のコンテキストのデータにアクセスしたいケースでどう書けばよいのか。

サンプル

例えばこんなJSONデータがあったとする。

var context = {
  title: "My First Blog Post!",
  author: {
    id: 47,
    name: "Yehuda Katz"
  },
  body: "My first post. Wheeeee!",
  comments:[
    {id:1,text:"aaa"},
    {id:2,text:"bbb"},
    {id:3,text:"ccc"},
    {id:4,text:"ddd"},
    {id:5,text:"eee"}
  ]
};

commentsの繰り返しの際、{{text}}は{{comment.text}}ではなく{{text}}と書ける。

<h1>Comments</h1>
<div id="comments">
  {{#each comments}}
     <p>{{text}}</p>
  {{/each}}
</div>

comments内でauthor.idを使いたい場合、eachブロック内からはauthor.idは親コンテキストに属するため「../」を使ってアクセスする。

<h1>Comments</h1>
<div id="comments">
  {{#each comments}}
     <p>{{../author}}</p>
     <p>{{text}}</p>
  {{/each}}
</div>

公式ページには「../」セグメントは親のテンプレートパスを参照し、コンテキストの1階層上という訳ではないと書いてあり、これがどういう意味かというと、{{#}}〜{{/}}のブロックを1セグメントとみなし、これが深くなる(入れ子になる)に従って取得可能なデータのコンテキストが変化するということらしい。

<h1>Comments</h1>
<div id="comments">
  {{#each comments}}
     <p>{{../author}}</p>
     <p>{{text}}</p>
     {{#if user}}
  //ここで深くなる!!
       <p>{{text}}</p>
     {{/if}}
  {{/each}}
</div>

上記の例でいうとdepth[0]の状態が、#each内ではdepth[1]になり、#ifでdepth[2]になる。
なので、JSON上の最上位(depth[0])にあるauthorをコメント内で存在チェックしつつさらに値を取得するようなケースでは ../../ として2段階上がる必要がある。

<h1>Comments</h1>
<div id="comments">
  {{#each comments}}
     <p>{{../author}}</p>
     <p>{{text}}</p>
     {{#if ../author}}
       <p>{{../../author.name}}</p>
     {{/if}}
  {{/each}}
</div>

説明が分かりにくいと思うので、実際に試してみることを推奨。
デバッガで追う際にはtemplateメソッドのdepthsパラメータの値を追うと良い。