LoginSignup
12
12

More than 5 years have passed since last update.

AngularDart入門 第2回 HelloWorld改

Last updated at Posted at 2014-10-25

第1回では最も単純なAngularDartアプリケーションを作りました。今回はHelloWorld改ということでもう少しAngularDartの機能を使ってみましょう。

今回の元記事は2. Building Something More than Hello Worldです。

まずはサンプルアプリを動かしてみよう

こちらにサンプルアプリのソースコードがあります。リポジトリをクローンして、Chapter_02ディレクトリで> pub serveすればサンプルアプリが起動します。

Imgur

Recipe Listのアイテムをクリックすると下にレシピの詳細が表示されます。

スコープを理解する

AngularDartにはスコープ(Scope)という概念があります。スコープはHTMLの要素に対応した入れ子構造になっており、ルートスコープ(Root Scope)が前回説明したng-appが付いた要素です。ルートスコープは必ず<html>要素に対して定義されますが、その子になるスコープは自由に定義することができます。ただし、ルートスコープ以外のスコープは必ず親スコープを持ちます。

Scope diagram

モデルを理解する

前回のコードに次のようなバインディングがありました。

<input type="text" ng-model="name">

このnameはモデルですが、モデルは常にスコープに紐付いています。前回はルートスコープ以外にスコープがありませんでしたので、このnameはルートスコープ(ng-app)に紐付いたモデルだったということです。Angularでモデルを扱う場合は、そのモデルがどのスコープに紐付いているのかを把握していなければなりません。

コンポーネントを理解する

コンポーネントというのはスコープを持つオブジェクトです。アプリケーションにコンポーネントをひもづけることで、アプリケーション内に独自のスコープを定義することができます。

コンポーネントを定義するには@Componentアノテーションをクラスに付けます。

@Component(
  selector: 'recipe-book',
  templateUrl: 'recipe_book.html'
)
class RecipeBookComponent {

@Componentにはいくつかの引数があります。selectorはそのコンポーネントのCSSセレクタを設定します。[recipe-book]は、html内ではrecipe-book属性として宣言します。宣言には以下の様な種類があります。

  • recipe-book : DOM要素
  • .recipe-book : クラス
  • [recipe-book] : DOM属性
  • [attribute=value]: 条件付きDOM属性
  • `:contains(/recipe-book/) : 任意の文字列を含む要素

templateUrlにはそのコンポーネントのテンプレートとなるHTMLを指定します。記述するUrlは基本的にはpackages/から始まる相対パスですが後述するtransformerの設定によりファイル名のみに省略できます。

recipe_book.html
<div><strong>Name: </strong>{{selectedRecipe.name}}</div>

<li ng-click="selectRecipe(recipe)">{{recipe.name}}</li>

publishAsはhtml内でのコンポーネントのインスタンス名です。publishAsに設定した名前と同じ名前のgetterを作り、thisを返す必要があります。publishAsを設定すると、モデルへのアクセスはcmp.selectedRecipeのようになります。設定しなかった場合はselectedRecipeとするだけでアクセスできますが、先述の通りスコープは入れ子になっているのでどのスコープに属するモデルなのか明確にするために出来るだけ設定しましょう。

[追記]
publishAsは現在Deprecatedされています。後方互換性のために残されていますが実際の処理は何も行われていません。現在は何もしなくても@Componentのオブジェクトが暗黙のルートスコープになっています。

このようにして作ったコンポーネントはアプリケーションに紐付けなければなりません。モジュールを宣言し、モジュールにコンポーネントを紐付け、そのモジュールをアプリケーションに追加します。

main.dart
import 'package:angular/angular.dart';
import 'package:angular/application_factory.dart';
import 'package:angular_sample/component/recipe_book.dart';

class MyAppModule extends Module {
  MyAppModule() {
    bind(RecipeBookComponent);
  }
}

void main() {
  applicationFactory()
  .addModule(new MyAppModule())
  .run();
}

アプリケーションにコンポーネントを紐付けたら、HTML内で呼び出しましょう。

<recipe-book></recipe_book>

<recipe-book>要素の内側がRecipeBookComponentのスコープになります。

[追記]
AngularDart 1系ではControllerという概念は取り払っているので、属性によりScopeを付与して操作するという以前の方法はあまり推奨されません(可能ではある)。なので基本的にはすべてComponent化して、テンプレートHTMLを別ファイルに書きます。

AngularDartを使うためにはangularパッケージへの依存を記述します。web_componentsはWeb Componentsに対応していない古いブラウザに対するポリフィルのパッケージです。外してもいいですが、その場合は後述のHTML内のweb_components依存部分を削除してください。

[追記]transformerによるHTMLファイルの変換

ComponentのtemplateUrlに指定するHTMLファイルや、cssUrlに指定するCSSファイルは基本的にはpackages/angular_sample/component/recipe_book.htmlのような相対パスを書く必要がありますが、これはとても面倒なのでAngularDartではpubspecのtransformerを使ってrecipe_book.htmlだけで記述できるようにしてあります。

pubspec.yamlのtransformersに次のように追記します。

transformers:
- angular:
    html_files:
      - lib/component/recipe_book.html

Angularの機能

ng-repeat

ng-repeatは、反復可能なオブジェクトに対して、テンプレートに当てはめて子要素を追加します。今回の内容がなんとなく理解できていれば、ng-repeat="recipe in cmp.recipes"publishAs:recipeなコンポーネントの定義であることがわかると思います。

<ul>
  <li class="pointer" ng-repeat="recipe in recipes" ng-click="selectRecipe(recipe)">
    {{recipe.name}}
  </li>
</ul>

ng-click

ng-clickはクリックイベントが起きた時に実行する式を設定できます。

まとめ

  • モデルはスコープに属する
  • コンポーネントはスコープを持つ
  • コンポーネントはアプリケーションに紐付ける

第3回3. Creating a Custom Component
を元にバージョン1.0に置き換えて解説します。

12
12
0

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
12
12