LoginSignup
4
4

More than 5 years have passed since last update.

今日はテンプレートを組み合わせて複雑なテンプレートを構築する方法を説明します。

まずJavaScriptのコードを見てみましょう。

var App = Ember.Application.create();

App.UserView = Ember.View.extend({
  templateName: 'user',
  lhs: 8,
  firstName: "Albert",
  lastName: "Hofmann",
  infoView: Ember.View.extend({
    templateName: 'info',
    posts: 25,    hobbies: "Riding bicycles",
    subInfoView: Ember.View.extend({
      templateName: 'subInfo',
      country: 'Japan'
    })
  })
});

App.UserView.create().append();

ViewクラスがUserView -> infoView -> subInfoView と階層構造を作っています。
それぞれのViewクラスは、テンプレートを指定するためのテンプレート名をtemplateNameメンバで指定します。
create().append() メソッドチェインで、明示的に描画を行なっています。
次にテンプレートを見てみます。

  <script type="text/x-handlebars" data-template-name="user">
    {{firstName}} {{lastName}}
    <br>
    {{view infoView}}
  </script>

  <script type="text/x-handlebars" data-template-name="info">
    <b>posts:</b> {{view.posts}}
    <br>
    <b>hobbies:</b> {{view.hobbies}}
    <br>
    {{view view.subInfoView}}
  </script>

  <script type="text/x-handlebars" data-template-name="subInfo">
    <b>country:</b> {{view.country}}
  </script>

それぞれのViewのためのテンプレートを1つずつ定義しています。
{{view}}ヘルパを使って、子供Viewを指定しています。
子供Viewのテンプレートでは、変数スコープは親Viewのままになります。子供Viewのインスタンスを参照するためには、view変数のメンバにアクセスします。(このあたり、直感に反する動きで、かなり理解に手こずりました。)

viewのコンテキストの扱いが最近変わったようです。
https://gist.github.com/2494968

このプログラムは以下のHTMLを出力します。(バインディングのためのマークは省略しています)

    Albert Hofmann
    <br>
    <b>posts:</b> 25
    <br>
    <b>hobbies:</b> Riding bicycles
    <br>
    <b>country:</b> Japan

Viewの階層構造を表現するためでなく、テンプレート部品化のためにテンプレートを分けることもできます。
サンプルを見てみましょう。

var App = Ember.Application.create();

App.UserView = Ember.View.extend({
  templateName: 'user',
  lhs: 8,
  firstName: "Albert",
  lastName: "Hofmann",
  posts: 25,
  hobbies: "Riding bicycles",
  country: 'Japan'
});

App.InfoView = Ember.View.extend({
    templateName: 'info'
});

App.SubInfoView = Ember.View.extend({
  templateName: 'subInfo',
});

App.UserView.create().append();

テンプレートを指定するためだけに、InfoView, SubInfoViewを定義しています。
続いてテンプレートのコードを見てみましょう。

  <script type="text/x-handlebars" data-template-name="user">
    {{firstName}} {{lastName}}
    <br>
    {{view App.InfoView}}
  </script>

  <script type="text/x-handlebars" data-template-name="info">
    <b>posts:</b> {{posts}}
    <br>
    <b>hobbies:</b> {{hobbies}}
    <br>
    {{view App.SubInfoView}}
  </script>

  <script type="text/x-handlebars" data-template-name="subInfo">
    <b>country:</b> {{country}}
  </script>

{{view}}ヘルパの引数には、Viewクラスへのグローバルパスを指定します。
Viewクラス名が大文字で始まっていないと、Ember.jsはグローバルパスと認識しないようなので注意してください。
今回は子供Viewで参照するのは、元ViewであるUserViewのメンバなので、viewメンバ経由でなく、直接変数を参照しています。
このプログラムは以下のHTMLを出力します。(バインディングのためのマークは省略しています)

    Albert Hofmann
    <br>
    <b>posts:</b> 25
    <br>
    <b>hobbies:</b> Riding bicycles
    <br>
    <b>country:</b> Japan

今日はViewを階層化する方法について見てきました。
変数のスコープの扱いが私の直感と違っていたため、理解するのに苦労しました。
このあたり、Ember.jsの学習の鬼門になりそうな気がします。
また、テンプレートから実際にはないメンバを指定した時にエラーなどを出力してくれないため、原因の特定に手間取りました。この奥ゆかしい挙動は、バグの原因特定を困難にするので、変えて欲しいところです。

4
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4