実践入門 Ember.js

第4回 ユーザのインタラクション(Controller, Component)

この記事を読むのに必要な時間:およそ 6 分

Component

Componentは画面上のひとまとまりの部品をカプセル化したものです。

例えば,次のようなComponentを定義した場合を考えてみましょう。

Componentのクラス定義

App.HelloWorldComponent = Ember.Component.extend({
  message: 'Hello World'
});

Componentのテンプレート

<script type="text/x-handlebars" data-template-name="components/hello-world">
  <b>{{message}} !</b>
</script>

ポイントは次のとおりです。

  • クラスとテンプレートをセットで定義します。
  • Component名は,クラス名からComponentを削除し,単語の区切りを-(ハイフン)で表現したものになります。

    テンプレート名はcomponents/+Component名です。

    クラス名 Component名 テンプレート名
    HelloWorldComponent hello-world components/hello-world

    また,このテンプレートのコンテキストはComponent自身です。

  • Componentを使う際はテンプレートの任意の場所でComponent名を記述します。

    He said, {{hello-world}}
  • Componentを使う際,必要に応じてComponentのプロパティを設定できます。

    He said, {{hello-world message="This is awesome"}}
  • 描画されたHTMLはdivタグで囲まれます。

    他のタグに変更する場合,tagNameプロパティを上書きします。

    {{hello-world tagName="span"}}

    また,タグを生成したくない場合はtagNameに空文字を与えます。

    {{hello-world tagName=""}}
    
  • Component名は必ず2単語以上で-(ハイフン)を含む必要があります。

    これは,将来的にはWeb Componentsとの統合が視野に入れられているためです(Web Componentsはタグ名に-(ハイフン)を含む必要があります)⁠

    Ember.js 1.11.0からは,Componentを利用する際は{{hello-world}}ではなく,<hello-world>と記述できるようになる予定です(参照:The Road to Ember 2.0 RFC #15)⁠

  • テンプレートのみで十分な場合,クラス定義は省略可能です。

今回はこのComponentを使って,テキストを省略して表示する機能をもったパーツを作成してみましょう。

App.TruncateTextComponent = Ember.Component.extend({
  text: null,
  length: 20,
  isExpanded: false,
  expandText: 'もっと見る',

  actions: {
    expand: function() {
      this.set('isExpanded', true);
    }
  }
});

ComponentはControllerと同様,アクションを定義できます。

次はComponentのテンプレートを作成します。

<script type="text/x-handlebars" data-template-name="components/truncate-text">
  {{#if isExpanded}}
    {{text}}
  {{else}}
    {{truncate text length=length}} <a href="#" {{action "expand"}}>{{expandText}}</a>
  {{/if}}
</script>

これでComponentを用意できました。 では,このComponentを実際に使ってみましょう。

記事詳細のテンプレートを以下のように書き換えてください。

<script type="text/x-handlebars" data-template-name="posts/show">
  <h2>{{model.title}}</h2>

  <pre>
    {{truncate-text text=model.body}}
  </pre>

  {{link-to "戻る" "posts.index"}}
</script>

Componentは画面が切り替わると破棄されるため,コントローラで「記事を省略して表示するかどうか」のフラグは不要になりました。 RoutesetupControllerでコントローラの初期化をしている部分を削除しましょう。

App.PostsShowRoute = Ember.Route.extend({
  model: function(params) {
    return this.modelFor('posts').filter(function(post) {
      return post.id === Number(params.post_id);
    })[0];
  }
});

そうすると,App.PostsShowControllerも定義する必要ななくなるので削除します。

これで,コントローラで実装した場合と違って,わざわざフラグを初期化しなくてもそれぞれの記事ごとに折り畳みの状態が保持されるようになりました。

まとめ

今回はユーザのインタラクションを受け取る方法を解説しました。

Controller,Componentは今回紹介したもの以外にもまだまだ機能があります。 それらについて今後の記事で随時解説する予定です。

次回はEmber.jsが提供する汎用的な機能を解説します。

著者プロフィール

佐藤竜之介(さとうりゅうのすけ)

株式会社えにしテック所属。JavaScriptとRubyが好きなウェブ系プログラマ。オープンソースソフトウェアに強い関心がありEmber.jsにも数多くのパッチを送っている。

ブログ:http://tricknotes.hateblo.jp/
Twitter:@tricknotes

コメント

コメントの記入