ほげにっき

hogedigoの日記

AngularJSチュートリアルやってメモメモ(step10 - イベントハンドラ)

このステップでは端末詳細ビューにクリックすると端末画像が切り替わる部品を追加する。


目次


今回やるのはこちら↓
AngularJS: 10 - Event Handlers


ワークスペースをstep10のにリセット。注:ローカルの修正は破棄される

git checkout -f step-10

ローカルサーバーをリフレッシュ(またはAngularサーバーで確認可)。

端末詳細ビューを見ると、選択されている端末の大きな画像1枚と、小さないくつかのサムネイル画像を表示している。サムネイル画像をクリックしたら大きな画像が切り替わる。
以降でAngularでどの様に実現するのか見てみよう。


step9からstep10への変更を説明。diffはこちら

コントローラー

app/js/controllers.js:

...
function PhoneDetailCtrl($scope, $routeParams, $http) {
  $http.get('phones/' + $routeParams.phoneId + '.json').success(function(data) {
    $scope.phone = data;
    $scope.mainImageUrl = data.images[0];
  });
 
  $scope.setImage = function(imageUrl) {
    $scope.mainImageUrl = imageUrl;
  }
}
 
//PhoneDetailCtrl.$inject = ['$scope', '$routeParams', '$http'];

PhoneDetailCtrlコントローラーではmainImageUrlモデルプロパティを作成し、デフォルト値として最初の端末画像URLをセットしている。

さらに、mainImageUrlの値を変更するsetImageイベントハンドラ関数を作成している。

テンプレート

app/partials/phone-detail.html:

<img ng-src="{{mainImageUrl}}" class="phone">
 
...
 
<ul class="phone-thumbs">
  <li ng-repeat="img in phone.images">
    <img ng-src="{{img}}" ng-click="setImage(img)">
  </li>
</ul>
...

大きな画像を表示するimg要素で、ngSrcディレクティブをmainImageUrlプロパティにバインドしている。

また、サムネイル画像にngClickハンドラを設定している。ユーザーがサムネイル画像の一つをクリックするとハンドラはsetImageイベントハンドラ関数を呼び出し、mainImageUrlプロパティを、クリックされたサムネイルの画像URLに変更する。

テスト

この新機能を検証するのに、end-to-endテストを2つ追加する。一つはメイン画像にデフォルトで最初の端末画像が設定されていることを検証する。二つ目のテストはサムネイル画像をクリックしてメイン画像が適切に切り替わることをテストする。

test/e2e/scenarios.js:

...
  describe('Phone detail view', function() {
 
...
 
    it('should display the first phone image as the main phone image', function() {
      expect(element('img.phone').attr('src')).toBe('img/phones/nexus-s.0.jpg');
    });
 
 
    it('should swap main image if a thumbnail image is clicked on', function() {
      element('.phone-thumbs li:nth-child(3) img').click();
      expect(element('img.phone').attr('src')).toBe('img/phones/nexus-s.2.jpg');
 
      element('.phone-thumbs li:nth-child(1) img').click();
      expect(element('img.phone').attr('src')).toBe('img/phones/nexus-s.0.jpg');
    });
  });
});

./scripts/e2e-test.shまたは、ent-to-endテストランナーのブラウザタブを更新してテストを実行する。またはAngularのサーバーでテスト実行を確認できる。

実験

  • PhoneDetailCtrlに新しいメソッドを追加しよう
$scope.hello = function(name) {
        alert('Hello ' + (name || 'world') + '!');
}
  • そしてphone-details.htmlテンプレートに以下を追加してみよう
<button ng-click="hello('Elmo')">Hello</button>


今日はここまで。次回はいよいよチュートリアル最終回「step11 - RESTとカスタムサービス」。